@rev-net/core-v6 0.0.30 → 0.0.31

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 (62) hide show
  1. package/USER_JOURNEYS.md +11 -0
  2. package/package.json +8 -8
  3. package/script/Deploy.s.sol +4 -1
  4. package/src/REVDeployer.sol +4 -2
  5. package/src/REVLoans.sol +81 -59
  6. package/src/REVOwner.sol +40 -11
  7. package/src/interfaces/IREVLoans.sol +5 -0
  8. package/test/REV.integrations.t.sol +10 -1
  9. package/test/REVAutoIssuanceFuzz.t.sol +10 -1
  10. package/test/REVDeployerRegressions.t.sol +12 -1
  11. package/test/REVInvincibility.t.sol +21 -2
  12. package/test/REVLifecycle.t.sol +12 -1
  13. package/test/REVLoans.invariants.t.sol +12 -1
  14. package/test/REVLoansAttacks.t.sol +12 -1
  15. package/test/REVLoansFeeRecovery.t.sol +12 -1
  16. package/test/REVLoansFindings.t.sol +12 -1
  17. package/test/REVLoansRegressions.t.sol +12 -1
  18. package/test/REVLoansSourceFeeRecovery.t.sol +12 -1
  19. package/test/REVLoansSourced.t.sol +12 -1
  20. package/test/REVLoansUnSourced.t.sol +12 -1
  21. package/test/TestBurnHeldTokens.t.sol +12 -1
  22. package/test/TestCEIPattern.t.sol +12 -1
  23. package/test/TestCashOutCallerValidation.t.sol +13 -2
  24. package/test/TestConversionDocumentation.t.sol +12 -1
  25. package/test/TestCrossCurrencyReclaim.t.sol +12 -1
  26. package/test/TestCrossSourceReallocation.t.sol +12 -1
  27. package/test/TestERC2771MetaTx.t.sol +12 -1
  28. package/test/TestEmptyBuybackSpecs.t.sol +12 -1
  29. package/test/TestFlashLoanSurplus.t.sol +12 -1
  30. package/test/TestHiddenTokens.t.sol +12 -1
  31. package/test/TestHookArrayOOB.t.sol +12 -1
  32. package/test/TestLiquidationBehavior.t.sol +12 -1
  33. package/test/TestLoanSourceRotation.t.sol +12 -1
  34. package/test/TestLoansCashOutDelay.t.sol +12 -1
  35. package/test/TestLongTailEconomics.t.sol +12 -1
  36. package/test/TestLowFindings.t.sol +12 -1
  37. package/test/TestMixedFixes.t.sol +12 -1
  38. package/test/TestPermit2Signatures.t.sol +12 -1
  39. package/test/TestReallocationSandwich.t.sol +12 -1
  40. package/test/TestRevnetRegressions.t.sol +14 -2
  41. package/test/TestSplitWeightAdjustment.t.sol +12 -1
  42. package/test/TestSplitWeightE2E.t.sol +14 -1
  43. package/test/TestSplitWeightFork.t.sol +14 -1
  44. package/test/TestStageTransitionBorrowable.t.sol +12 -1
  45. package/test/TestSwapTerminalPermission.t.sol +12 -1
  46. package/test/TestUint112Overflow.t.sol +12 -1
  47. package/test/TestZeroAmountLoanGuard.t.sol +12 -1
  48. package/test/TestZeroRepayment.t.sol +12 -1
  49. package/test/audit/CodexPhantomSurplusTerminal.t.sol +367 -0
  50. package/test/audit/LoanIdOverflowGuard.t.sol +12 -1
  51. package/test/audit/NemesisOperatorDelegation.t.sol +12 -1
  52. package/test/fork/ForkTestBase.sol +14 -1
  53. package/test/mock/MockBuybackCashOutRecorder.sol +2 -0
  54. package/test/mock/MockBuybackDataHook.sol +3 -1
  55. package/test/mock/MockBuybackDataHookMintPath.sol +2 -0
  56. package/test/mock/MockSuckerRegistry.sol +17 -0
  57. package/test/regression/TestBurnPermissionRequired.t.sol +12 -1
  58. package/test/regression/TestCashOutBuybackFeeLeak.t.sol +14 -1
  59. package/test/regression/TestCrossRevnetLiquidation.t.sol +12 -1
  60. package/test/regression/TestCumulativeLoanCounter.t.sol +12 -1
  61. package/test/regression/TestLiquidateGapHandling.t.sol +12 -1
  62. package/test/regression/TestZeroPriceFeed.t.sol +12 -1
@@ -13,6 +13,8 @@ import "@bananapus/suckers-v6/src/JBSuckerRegistry.sol";
13
13
  import "@bananapus/721-hook-v6/src/JB721TiersHook.sol";
14
14
  import "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
15
15
  import "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
16
+ import "@bananapus/721-hook-v6/src/JB721CheckpointsDeployer.sol";
17
+ import {IJB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/interfaces/IJB721CheckpointsDeployer.sol";
16
18
  import "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
17
19
  import "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
18
20
  import "@bananapus/buyback-hook-v6/src/interfaces/IJBBuybackHookRegistry.sol";
@@ -39,6 +41,7 @@ import {REVStageConfig} from "../../src/structs/REVStageConfig.sol";
39
41
  import {REVAutoIssuance} from "../../src/structs/REVAutoIssuance.sol";
40
42
  import {REVSuckerDeploymentConfig} from "../../src/structs/REVSuckerDeploymentConfig.sol";
41
43
  import {IREVDeployer} from "../../src/interfaces/IREVDeployer.sol";
44
+ import {MockSuckerRegistry} from "../mock/MockSuckerRegistry.sol";
42
45
 
43
46
  contract NemesisOperatorDelegationTest is TestBaseWorkflow {
44
47
  bytes32 internal constant REV_DEPLOYER_SALT = "REVDeployer";
@@ -71,7 +74,14 @@ contract NemesisOperatorDelegationTest is TestBaseWorkflow {
71
74
  SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
72
75
  HOOK_STORE = new JB721TiersHookStore();
73
76
  EXAMPLE_HOOK = new JB721TiersHook(
74
- jbDirectory(), jbPermissions(), jbPrices(), jbRulesets(), HOOK_STORE, jbSplits(), multisig()
77
+ jbDirectory(),
78
+ jbPermissions(),
79
+ jbPrices(),
80
+ jbRulesets(),
81
+ HOOK_STORE,
82
+ jbSplits(),
83
+ IJB721CheckpointsDeployer(address(new JB721CheckpointsDeployer())),
84
+ multisig()
75
85
  );
76
86
  ADDRESS_REGISTRY = new JBAddressRegistry();
77
87
  HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
@@ -80,6 +90,7 @@ contract NemesisOperatorDelegationTest is TestBaseWorkflow {
80
90
 
81
91
  LOANS = new REVLoans({
82
92
  controller: jbController(),
93
+ suckerRegistry: IJBSuckerRegistry(address(new MockSuckerRegistry())),
83
94
  revId: FEE_PROJECT_ID,
84
95
  owner: address(this),
85
96
  permit2: permit2(),
@@ -34,6 +34,8 @@ import {JBSuckerRegistry} from "@bananapus/suckers-v6/src/JBSuckerRegistry.sol";
34
34
  import {JB721TiersHookDeployer} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
35
35
  import {JB721TiersHook} from "@bananapus/721-hook-v6/src/JB721TiersHook.sol";
36
36
  import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
37
+ import {JB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/JB721CheckpointsDeployer.sol";
38
+ import {IJB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/interfaces/IJB721CheckpointsDeployer.sol";
37
39
  import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
38
40
  import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
39
41
  import {IJBRulesetDataHook} from "@bananapus/core-v6/src/interfaces/IJBRulesetDataHook.sol";
@@ -44,6 +46,8 @@ import {JB721TierConfig} from "@bananapus/721-hook-v6/src/structs/JB721TierConfi
44
46
  import {JB721TierConfigFlags} from "@bananapus/721-hook-v6/src/structs/JB721TierConfigFlags.sol";
45
47
  import {JB721InitTiersConfig} from "@bananapus/721-hook-v6/src/structs/JB721InitTiersConfig.sol";
46
48
  import {IJB721TokenUriResolver} from "@bananapus/721-hook-v6/src/interfaces/IJB721TokenUriResolver.sol";
49
+ import "@bananapus/721-hook-v6/src/JB721CheckpointsDeployer.sol";
50
+ import {IJB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/interfaces/IJB721CheckpointsDeployer.sol";
47
51
  import {REVDeploy721TiersHookConfig} from "../../src/structs/REVDeploy721TiersHookConfig.sol";
48
52
  import {REVBaseline721HookConfig} from "../../src/structs/REVBaseline721HookConfig.sol";
49
53
  import {REV721TiersHookFlags} from "../../src/structs/REV721TiersHookFlags.sol";
@@ -74,6 +78,7 @@ import {StateLibrary} from "@uniswap/v4-core/src/libraries/StateLibrary.sol";
74
78
  import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol";
75
79
  import {REVOwner} from "../../src/REVOwner.sol";
76
80
  import {IREVDeployer} from "../../src/interfaces/IREVDeployer.sol";
81
+ import {MockSuckerRegistry} from "../mock/MockSuckerRegistry.sol";
77
82
 
78
83
  /// @notice Helper that adds liquidity to a V4 pool via the unlock/callback pattern.
79
84
  contract LiquidityHelper is IUnlockCallback {
@@ -299,7 +304,14 @@ abstract contract ForkTestBase is TestBaseWorkflow {
299
304
  SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
300
305
  HOOK_STORE = new JB721TiersHookStore();
301
306
  EXAMPLE_HOOK = new JB721TiersHook(
302
- jbDirectory(), jbPermissions(), jbPrices(), jbRulesets(), HOOK_STORE, jbSplits(), multisig()
307
+ jbDirectory(),
308
+ jbPermissions(),
309
+ jbPrices(),
310
+ jbRulesets(),
311
+ HOOK_STORE,
312
+ jbSplits(),
313
+ IJB721CheckpointsDeployer(address(new JB721CheckpointsDeployer())),
314
+ multisig()
303
315
  );
304
316
  ADDRESS_REGISTRY = new JBAddressRegistry();
305
317
  HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
@@ -328,6 +340,7 @@ abstract contract ForkTestBase is TestBaseWorkflow {
328
340
 
329
341
  LOANS_CONTRACT = new REVLoans({
330
342
  controller: jbController(),
343
+ suckerRegistry: IJBSuckerRegistry(address(new MockSuckerRegistry())),
331
344
  revId: FEE_PROJECT_ID,
332
345
  owner: address(this),
333
346
  permit2: permit2(),
@@ -38,12 +38,14 @@ contract MockBuybackCashOutRecorder is IJBRulesetDataHook, IJBPayHook, IJBCashOu
38
38
  uint256 cashOutTaxRate,
39
39
  uint256 cashOutCount,
40
40
  uint256 totalSupply,
41
+ uint256 effectiveSurplusValue,
41
42
  JBCashOutHookSpecification[] memory hookSpecifications
42
43
  )
43
44
  {
44
45
  cashOutTaxRate = JBConstants.MAX_CASH_OUT_TAX_RATE;
45
46
  cashOutCount = context.cashOutCount;
46
47
  totalSupply = context.totalSupply;
48
+ effectiveSurplusValue = 0;
47
49
  hookSpecifications = new JBCashOutHookSpecification[](1);
48
50
  hookSpecifications[0] = JBCashOutHookSpecification({
49
51
  hook: IJBCashOutHook(address(this)),
@@ -44,16 +44,18 @@ contract MockBuybackDataHook is IJBRulesetDataHook, IJBPayHook {
44
44
  uint256 cashOutTaxRate,
45
45
  uint256 cashOutCount,
46
46
  uint256 totalSupply,
47
+ uint256 effectiveSurplusValue,
47
48
  JBCashOutHookSpecification[] memory hookSpecifications
48
49
  )
49
50
  {
50
51
  cashOutTaxRate = cashOutTaxRateToReturn == 0 ? context.cashOutTaxRate : cashOutTaxRateToReturn;
51
52
  cashOutCount = cashOutCountToReturn == 0 ? context.cashOutCount : cashOutCountToReturn;
52
53
  totalSupply = totalSupplyToReturn == 0 ? context.totalSupply : totalSupplyToReturn;
54
+ effectiveSurplusValue = 0;
53
55
 
54
56
  if (!shouldReturnCashOutHookSpec) {
55
57
  hookSpecifications = new JBCashOutHookSpecification[](0);
56
- return (cashOutTaxRate, cashOutCount, totalSupply, hookSpecifications);
58
+ return (cashOutTaxRate, cashOutCount, totalSupply, effectiveSurplusValue, hookSpecifications);
57
59
  }
58
60
 
59
61
  hookSpecifications = new JBCashOutHookSpecification[](1);
@@ -35,12 +35,14 @@ contract MockBuybackDataHookMintPath is IJBRulesetDataHook, IJBPayHook {
35
35
  uint256 cashOutTaxRate,
36
36
  uint256 cashOutCount,
37
37
  uint256 totalSupply,
38
+ uint256 effectiveSurplusValue,
38
39
  JBCashOutHookSpecification[] memory hookSpecifications
39
40
  )
40
41
  {
41
42
  cashOutTaxRate = context.cashOutTaxRate;
42
43
  cashOutCount = context.cashOutCount;
43
44
  totalSupply = context.totalSupply;
45
+ effectiveSurplusValue = 0;
44
46
  hookSpecifications = new JBCashOutHookSpecification[](0);
45
47
  }
46
48
 
@@ -0,0 +1,17 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity 0.8.28;
3
+
4
+ /// @notice Minimal mock that returns zeros for all cross-chain queries.
5
+ contract MockSuckerRegistry {
6
+ function isSuckerOf(uint256, address) external pure returns (bool) {
7
+ return false;
8
+ }
9
+
10
+ function remoteTotalSupplyOf(uint256) external pure returns (uint256) {
11
+ return 0;
12
+ }
13
+
14
+ function remoteSurplusOf(uint256, uint256, uint256) external pure returns (uint256) {
15
+ return 0;
16
+ }
17
+ }
@@ -35,6 +35,8 @@ import {JBSuckerRegistry} from "@bananapus/suckers-v6/src/JBSuckerRegistry.sol";
35
35
  import {JB721TiersHookDeployer} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
36
36
  import {JB721TiersHook} from "@bananapus/721-hook-v6/src/JB721TiersHook.sol";
37
37
  import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
38
+ import {JB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/JB721CheckpointsDeployer.sol";
39
+ import {IJB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/interfaces/IJB721CheckpointsDeployer.sol";
38
40
  import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
39
41
  import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
40
42
  import {REVEmpty721Config} from "../helpers/REVEmpty721Config.sol";
@@ -42,6 +44,7 @@ import {JBPermissionIds} from "@bananapus/permission-ids-v6/src/JBPermissionIds.
42
44
  import {JBPermissioned} from "@bananapus/core-v6/src/abstract/JBPermissioned.sol";
43
45
  import {REVOwner} from "../../src/REVOwner.sol";
44
46
  import {IREVDeployer} from "../../src/interfaces/IREVDeployer.sol";
47
+ import {MockSuckerRegistry} from "../mock/MockSuckerRegistry.sol";
45
48
 
46
49
  /// @notice Validates that borrowFrom() reverts with a clear error when the caller hasn't granted BURN_TOKENS
47
50
  /// permission to the REVLoans contract.
@@ -89,7 +92,14 @@ contract TestBurnPermissionRequired is TestBaseWorkflow {
89
92
  SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
90
93
  HOOK_STORE = new JB721TiersHookStore();
91
94
  EXAMPLE_HOOK = new JB721TiersHook(
92
- jbDirectory(), jbPermissions(), jbPrices(), jbRulesets(), HOOK_STORE, jbSplits(), multisig()
95
+ jbDirectory(),
96
+ jbPermissions(),
97
+ jbPrices(),
98
+ jbRulesets(),
99
+ HOOK_STORE,
100
+ jbSplits(),
101
+ IJB721CheckpointsDeployer(address(new JB721CheckpointsDeployer())),
102
+ multisig()
93
103
  );
94
104
  ADDRESS_REGISTRY = new JBAddressRegistry();
95
105
  HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
@@ -102,6 +112,7 @@ contract TestBurnPermissionRequired is TestBaseWorkflow {
102
112
  .addPriceFeedFor(0, uint32(uint160(address(TOKEN))), uint32(uint160(JBConstants.NATIVE_TOKEN)), priceFeed);
103
113
  LOANS_CONTRACT = new REVLoans({
104
114
  controller: jbController(),
115
+ suckerRegistry: IJBSuckerRegistry(address(new MockSuckerRegistry())),
105
116
  revId: FEE_PROJECT_ID,
106
117
  owner: address(this),
107
118
  permit2: permit2(),
@@ -21,7 +21,11 @@ import {JBTokenAmount} from "@bananapus/core-v6/src/structs/JBTokenAmount.sol";
21
21
  import {JB721TiersHook} from "@bananapus/721-hook-v6/src/JB721TiersHook.sol";
22
22
  import {JB721TiersHookDeployer} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
23
23
  import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
24
+ import {JB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/JB721CheckpointsDeployer.sol";
25
+ import {IJB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/interfaces/IJB721CheckpointsDeployer.sol";
24
26
  import {IJB721TiersHookDeployer} from "@bananapus/721-hook-v6/src/interfaces/IJB721TiersHookDeployer.sol";
27
+ import "@bananapus/721-hook-v6/src/JB721CheckpointsDeployer.sol";
28
+ import {IJB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/interfaces/IJB721CheckpointsDeployer.sol";
25
29
  import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
26
30
  import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
27
31
  import {JBSuckerRegistry} from "@bananapus/suckers-v6/src/JBSuckerRegistry.sol";
@@ -37,6 +41,7 @@ import {REVEmpty721Config} from "../helpers/REVEmpty721Config.sol";
37
41
  import {MockBuybackCashOutRecorder} from "../mock/MockBuybackCashOutRecorder.sol";
38
42
  import {REVOwner} from "../../src/REVOwner.sol";
39
43
  import {IREVDeployer} from "../../src/interfaces/IREVDeployer.sol";
44
+ import {MockSuckerRegistry} from "../mock/MockSuckerRegistry.sol";
40
45
 
41
46
  /// @title TestCashOutBuybackFeeLeak
42
47
  /// @notice Proves the buyback hook callback receives only the non-fee cashOutCount (not the full count).
@@ -69,7 +74,14 @@ contract TestCashOutBuybackFeeLeak is TestBaseWorkflow {
69
74
  suckerRegistry = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
70
75
  hookStore = new JB721TiersHookStore();
71
76
  exampleHook = new JB721TiersHook(
72
- jbDirectory(), jbPermissions(), jbPrices(), jbRulesets(), hookStore, jbSplits(), multisig()
77
+ jbDirectory(),
78
+ jbPermissions(),
79
+ jbPrices(),
80
+ jbRulesets(),
81
+ hookStore,
82
+ jbSplits(),
83
+ IJB721CheckpointsDeployer(address(new JB721CheckpointsDeployer())),
84
+ multisig()
73
85
  );
74
86
  addressRegistry = new JBAddressRegistry();
75
87
  hookDeployer = new JB721TiersHookDeployer(exampleHook, hookStore, addressRegistry, multisig());
@@ -77,6 +89,7 @@ contract TestCashOutBuybackFeeLeak is TestBaseWorkflow {
77
89
  mockBuyback = new MockBuybackCashOutRecorder();
78
90
  loans = new REVLoans({
79
91
  controller: jbController(),
92
+ suckerRegistry: IJBSuckerRegistry(address(new MockSuckerRegistry())),
80
93
  revId: feeProjectId,
81
94
  owner: address(this),
82
95
  permit2: permit2(),
@@ -34,11 +34,14 @@ import {JBSuckerRegistry} from "@bananapus/suckers-v6/src/JBSuckerRegistry.sol";
34
34
  import {JB721TiersHookDeployer} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
35
35
  import {JB721TiersHook} from "@bananapus/721-hook-v6/src/JB721TiersHook.sol";
36
36
  import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
37
+ import {JB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/JB721CheckpointsDeployer.sol";
38
+ import {IJB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/interfaces/IJB721CheckpointsDeployer.sol";
37
39
  import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
38
40
  import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
39
41
  import {REVEmpty721Config} from "../helpers/REVEmpty721Config.sol";
40
42
  import {REVOwner} from "../../src/REVOwner.sol";
41
43
  import {IREVDeployer} from "../../src/interfaces/IREVDeployer.sol";
44
+ import {MockSuckerRegistry} from "../mock/MockSuckerRegistry.sol";
42
45
 
43
46
  /// @notice Validates that liquidateExpiredLoansFrom rejects loan number ranges that would overflow into another
44
47
  /// revnet's namespace.
@@ -87,7 +90,14 @@ contract TestCrossRevnetLiquidation is TestBaseWorkflow {
87
90
  SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
88
91
  HOOK_STORE = new JB721TiersHookStore();
89
92
  EXAMPLE_HOOK = new JB721TiersHook(
90
- jbDirectory(), jbPermissions(), jbPrices(), jbRulesets(), HOOK_STORE, jbSplits(), multisig()
93
+ jbDirectory(),
94
+ jbPermissions(),
95
+ jbPrices(),
96
+ jbRulesets(),
97
+ HOOK_STORE,
98
+ jbSplits(),
99
+ IJB721CheckpointsDeployer(address(new JB721CheckpointsDeployer())),
100
+ multisig()
91
101
  );
92
102
  ADDRESS_REGISTRY = new JBAddressRegistry();
93
103
  HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
@@ -100,6 +110,7 @@ contract TestCrossRevnetLiquidation is TestBaseWorkflow {
100
110
  .addPriceFeedFor(0, uint32(uint160(address(TOKEN))), uint32(uint160(JBConstants.NATIVE_TOKEN)), priceFeed);
101
111
  LOANS_CONTRACT = new REVLoans({
102
112
  controller: jbController(),
113
+ suckerRegistry: IJBSuckerRegistry(address(new MockSuckerRegistry())),
103
114
  revId: FEE_PROJECT_ID,
104
115
  owner: address(this),
105
116
  permit2: permit2(),
@@ -35,11 +35,14 @@ import {JBSuckerRegistry} from "@bananapus/suckers-v6/src/JBSuckerRegistry.sol";
35
35
  import {JB721TiersHookDeployer} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
36
36
  import {JB721TiersHook} from "@bananapus/721-hook-v6/src/JB721TiersHook.sol";
37
37
  import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
38
+ import {JB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/JB721CheckpointsDeployer.sol";
39
+ import {IJB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/interfaces/IJB721CheckpointsDeployer.sol";
38
40
  import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
39
41
  import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
40
42
  import {REVEmpty721Config} from "../helpers/REVEmpty721Config.sol";
41
43
  import {REVOwner} from "../../src/REVOwner.sol";
42
44
  import {IREVDeployer} from "../../src/interfaces/IREVDeployer.sol";
45
+ import {MockSuckerRegistry} from "../mock/MockSuckerRegistry.sol";
43
46
 
44
47
  /// @notice totalLoansBorrowedFor is a cumulative counter, not an active loan count.
45
48
  /// @dev The rename from numberOfLoansFor to totalLoansBorrowedFor clarifies that the counter only increments
@@ -90,7 +93,14 @@ contract TestCumulativeLoanCounter is TestBaseWorkflow {
90
93
  SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
91
94
  HOOK_STORE = new JB721TiersHookStore();
92
95
  EXAMPLE_HOOK = new JB721TiersHook(
93
- jbDirectory(), jbPermissions(), jbPrices(), jbRulesets(), HOOK_STORE, jbSplits(), multisig()
96
+ jbDirectory(),
97
+ jbPermissions(),
98
+ jbPrices(),
99
+ jbRulesets(),
100
+ HOOK_STORE,
101
+ jbSplits(),
102
+ IJB721CheckpointsDeployer(address(new JB721CheckpointsDeployer())),
103
+ multisig()
94
104
  );
95
105
  ADDRESS_REGISTRY = new JBAddressRegistry();
96
106
  HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
@@ -104,6 +114,7 @@ contract TestCumulativeLoanCounter is TestBaseWorkflow {
104
114
  );
105
115
  LOANS_CONTRACT = new REVLoans({
106
116
  controller: jbController(),
117
+ suckerRegistry: IJBSuckerRegistry(address(new MockSuckerRegistry())),
107
118
  revId: FEE_PROJECT_ID,
108
119
  owner: address(this),
109
120
  permit2: permit2(),
@@ -36,11 +36,14 @@ import {JBSuckerRegistry} from "@bananapus/suckers-v6/src/JBSuckerRegistry.sol";
36
36
  import {JB721TiersHookDeployer} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
37
37
  import {JB721TiersHook} from "@bananapus/721-hook-v6/src/JB721TiersHook.sol";
38
38
  import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
39
+ import {JB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/JB721CheckpointsDeployer.sol";
40
+ import {IJB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/interfaces/IJB721CheckpointsDeployer.sol";
39
41
  import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
40
42
  import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
41
43
  import {REVEmpty721Config} from "../helpers/REVEmpty721Config.sol";
42
44
  import {REVOwner} from "../../src/REVOwner.sol";
43
45
  import {IREVDeployer} from "../../src/interfaces/IREVDeployer.sol";
46
+ import {MockSuckerRegistry} from "../mock/MockSuckerRegistry.sol";
44
47
 
45
48
  /// @notice liquidateExpiredLoansFrom halts on deleted loan gaps.
46
49
  /// @dev Before the fix, the function used `break` when encountering a deleted loan (createdAt == 0),
@@ -93,7 +96,14 @@ contract TestLiquidateGapHandling is TestBaseWorkflow {
93
96
  SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
94
97
  HOOK_STORE = new JB721TiersHookStore();
95
98
  EXAMPLE_HOOK = new JB721TiersHook(
96
- jbDirectory(), jbPermissions(), jbPrices(), jbRulesets(), HOOK_STORE, jbSplits(), multisig()
99
+ jbDirectory(),
100
+ jbPermissions(),
101
+ jbPrices(),
102
+ jbRulesets(),
103
+ HOOK_STORE,
104
+ jbSplits(),
105
+ IJB721CheckpointsDeployer(address(new JB721CheckpointsDeployer())),
106
+ multisig()
97
107
  );
98
108
  ADDRESS_REGISTRY = new JBAddressRegistry();
99
109
  HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
@@ -106,6 +116,7 @@ contract TestLiquidateGapHandling is TestBaseWorkflow {
106
116
  .addPriceFeedFor(0, uint32(uint160(address(TOKEN))), uint32(uint160(JBConstants.NATIVE_TOKEN)), priceFeed);
107
117
  LOANS_CONTRACT = new REVLoans({
108
118
  controller: jbController(),
119
+ suckerRegistry: IJBSuckerRegistry(address(new MockSuckerRegistry())),
109
120
  revId: FEE_PROJECT_ID,
110
121
  owner: address(this),
111
122
  permit2: permit2(),
@@ -36,12 +36,15 @@ import {JBSuckerRegistry} from "@bananapus/suckers-v6/src/JBSuckerRegistry.sol";
36
36
  import {JB721TiersHookDeployer} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
37
37
  import {JB721TiersHook} from "@bananapus/721-hook-v6/src/JB721TiersHook.sol";
38
38
  import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
39
+ import {JB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/JB721CheckpointsDeployer.sol";
40
+ import {IJB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/interfaces/IJB721CheckpointsDeployer.sol";
39
41
  import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
40
42
  import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
41
43
  import {REVEmpty721Config} from "../helpers/REVEmpty721Config.sol";
42
44
  import {IJBPrices} from "@bananapus/core-v6/src/interfaces/IJBPrices.sol";
43
45
  import {REVOwner} from "../../src/REVOwner.sol";
44
46
  import {IREVDeployer} from "../../src/interfaces/IREVDeployer.sol";
47
+ import {MockSuckerRegistry} from "../mock/MockSuckerRegistry.sol";
45
48
 
46
49
  /// @notice Verifies that `_totalBorrowedFrom` gracefully handles zero-price feeds.
47
50
  /// @dev When a cross-currency price feed returns 0 (e.g., inverse truncation at low decimals), the affected source
@@ -96,7 +99,14 @@ contract TestZeroPriceFeed is TestBaseWorkflow {
96
99
  SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
97
100
  HOOK_STORE = new JB721TiersHookStore();
98
101
  EXAMPLE_HOOK = new JB721TiersHook(
99
- jbDirectory(), jbPermissions(), jbPrices(), jbRulesets(), HOOK_STORE, jbSplits(), multisig()
102
+ jbDirectory(),
103
+ jbPermissions(),
104
+ jbPrices(),
105
+ jbRulesets(),
106
+ HOOK_STORE,
107
+ jbSplits(),
108
+ IJB721CheckpointsDeployer(address(new JB721CheckpointsDeployer())),
109
+ multisig()
100
110
  );
101
111
  ADDRESS_REGISTRY = new JBAddressRegistry();
102
112
  HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
@@ -114,6 +124,7 @@ contract TestZeroPriceFeed is TestBaseWorkflow {
114
124
 
115
125
  LOANS_CONTRACT = new REVLoans({
116
126
  controller: jbController(),
127
+ suckerRegistry: IJBSuckerRegistry(address(new MockSuckerRegistry())),
117
128
  revId: FEE_PROJECT_ID,
118
129
  owner: address(this),
119
130
  permit2: permit2(),