@rev-net/core-v6 0.0.10 → 0.0.12

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 (49) hide show
  1. package/ADMINISTRATION.md +7 -7
  2. package/ARCHITECTURE.md +11 -11
  3. package/README.md +7 -4
  4. package/RISKS.md +2 -2
  5. package/SKILLS.md +8 -10
  6. package/STYLE_GUIDE.md +14 -1
  7. package/package.json +9 -9
  8. package/script/Deploy.s.sol +85 -35
  9. package/script/helpers/RevnetCoreDeploymentLib.sol +12 -5
  10. package/src/REVDeployer.sol +121 -129
  11. package/src/REVLoans.sol +14 -13
  12. package/src/interfaces/IREVDeployer.sol +25 -22
  13. package/src/structs/REVDeploy721TiersHookConfig.sol +12 -14
  14. package/test/REV.integrations.t.sol +17 -8
  15. package/test/REVAutoIssuanceFuzz.t.sol +9 -4
  16. package/test/REVDeployerRegressions.t.sol +13 -6
  17. package/test/REVInvincibility.t.sol +26 -12
  18. package/test/REVLifecycle.t.sol +9 -4
  19. package/test/REVLoans.invariants.t.sol +13 -6
  20. package/test/REVLoansAttacks.t.sol +12 -5
  21. package/test/REVLoansFeeRecovery.t.sol +12 -5
  22. package/test/REVLoansFindings.t.sol +16 -7
  23. package/test/REVLoansRegressions.t.sol +9 -4
  24. package/test/REVLoansSourced.t.sol +24 -11
  25. package/test/REVLoansUnSourced.t.sol +13 -6
  26. package/test/TestBurnHeldTokens.t.sol +16 -7
  27. package/test/TestCEIPattern.t.sol +12 -5
  28. package/test/TestCashOutCallerValidation.t.sol +12 -5
  29. package/test/TestConversionDocumentation.t.sol +25 -9
  30. package/test/TestCrossSourceReallocation.t.sol +12 -5
  31. package/test/TestEmptyBuybackSpecs.t.sol +23 -8
  32. package/test/TestFlashLoanSurplus.t.sol +12 -5
  33. package/test/TestHookArrayOOB.t.sol +19 -10
  34. package/test/TestLiquidationBehavior.t.sol +12 -5
  35. package/test/TestLowFindings.t.sol +16 -7
  36. package/test/TestMixedFixes.t.sol +16 -7
  37. package/test/TestSplitWeightAdjustment.t.sol +29 -12
  38. package/test/TestSplitWeightE2E.t.sol +24 -16
  39. package/test/TestSplitWeightFork.t.sol +20 -14
  40. package/test/TestStageTransitionBorrowable.t.sol +15 -5
  41. package/test/TestSwapTerminalPermission.t.sol +15 -5
  42. package/test/TestUint112Overflow.t.sol +12 -5
  43. package/test/TestZeroRepayment.t.sol +12 -5
  44. package/test/fork/ForkTestBase.sol +20 -14
  45. package/test/fork/TestCashOutFork.t.sol +8 -2
  46. package/test/fork/TestLoanCrossRulesetFork.t.sol +8 -2
  47. package/test/helpers/REVEmpty721Config.sol +45 -0
  48. package/test/regression/TestCumulativeLoanCounter.t.sol +12 -5
  49. package/test/regression/TestLiquidateGapHandling.t.sol +12 -5
@@ -7,6 +7,8 @@ import /* {*} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
7
7
  import /* {*} from */ "./../src/REVDeployer.sol";
8
8
  import "@croptop/core-v6/src/CTPublisher.sol";
9
9
  import {MockBuybackDataHook} from "./mock/MockBuybackDataHook.sol";
10
+ import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
11
+ import {REVCroptopAllowedPost} from "../src/structs/REVCroptopAllowedPost.sol";
10
12
 
11
13
  import "@bananapus/core-v6/script/helpers/CoreDeploymentLib.sol";
12
14
  import "@bananapus/721-hook-v6/script/helpers/Hook721DeploymentLib.sol";
@@ -177,8 +179,9 @@ contract REVnet_Integrations is TestBaseWorkflow {
177
179
 
178
180
  HOOK_STORE = new JB721TiersHookStore();
179
181
 
180
- EXAMPLE_HOOK =
181
- new JB721TiersHook(jbDirectory(), jbPermissions(), jbRulesets(), HOOK_STORE, jbSplits(), multisig());
182
+ EXAMPLE_HOOK = new JB721TiersHook(
183
+ jbDirectory(), jbPermissions(), jbPrices(), jbRulesets(), HOOK_STORE, jbSplits(), multisig()
184
+ );
182
185
 
183
186
  ADDRESS_REGISTRY = new JBAddressRegistry();
184
187
 
@@ -226,11 +229,13 @@ contract REVnet_Integrations is TestBaseWorkflow {
226
229
 
227
230
  // Configure the project.
228
231
  vm.prank(address(multisig()));
229
- REVNET_ID = REV_DEPLOYER.deployFor({
232
+ (REVNET_ID,) = REV_DEPLOYER.deployFor({
230
233
  revnetId: FEE_PROJECT_ID, // Zero to deploy a new revnet
231
234
  configuration: feeProjectConfig.configuration,
232
235
  terminalConfigurations: feeProjectConfig.terminalConfigurations,
233
- suckerDeploymentConfiguration: feeProjectConfig.suckerDeploymentConfiguration
236
+ suckerDeploymentConfiguration: feeProjectConfig.suckerDeploymentConfiguration,
237
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
238
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
234
239
  });
235
240
  }
236
241
 
@@ -355,11 +360,13 @@ contract REVnet_Integrations is TestBaseWorkflow {
355
360
  projectConfig.configuration.stageConfigurations = stageConfigurations;
356
361
  projectConfig.configuration.description.salt = "FeeChange";
357
362
 
358
- uint256 revnetProjectId = REV_DEPLOYER.deployFor({
363
+ (uint256 revnetProjectId,) = REV_DEPLOYER.deployFor({
359
364
  revnetId: 0, // Zero to deploy a new revnet
360
365
  configuration: projectConfig.configuration,
361
366
  terminalConfigurations: projectConfig.terminalConfigurations,
362
- suckerDeploymentConfiguration: projectConfig.suckerDeploymentConfiguration
367
+ suckerDeploymentConfiguration: projectConfig.suckerDeploymentConfiguration,
368
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
369
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
363
370
  });
364
371
 
365
372
  {
@@ -411,11 +418,13 @@ contract REVnet_Integrations is TestBaseWorkflow {
411
418
  abi.encodeWithSelector(REVDeployer.REVDeployer_Unauthorized.selector, FEE_PROJECT_ID, address(this))
412
419
  );
413
420
  // Configure the project.
414
- REVNET_ID = REV_DEPLOYER.deployFor({
421
+ (REVNET_ID,) = REV_DEPLOYER.deployFor({
415
422
  revnetId: FEE_PROJECT_ID, // Zero to deploy a new revnet
416
423
  configuration: feeProjectConfig.configuration,
417
424
  terminalConfigurations: feeProjectConfig.terminalConfigurations,
418
- suckerDeploymentConfiguration: feeProjectConfig.suckerDeploymentConfiguration
425
+ suckerDeploymentConfiguration: feeProjectConfig.suckerDeploymentConfiguration,
426
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
427
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
419
428
  });
420
429
  }
421
430
  }
@@ -26,6 +26,8 @@ import {JB721TiersHook} from "@bananapus/721-hook-v6/src/JB721TiersHook.sol";
26
26
  import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
27
27
  import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
28
28
  import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
29
+ import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
30
+ import {REVCroptopAllowedPost} from "../src/structs/REVCroptopAllowedPost.sol";
29
31
 
30
32
  /// @notice Fuzz tests for REVDeployer multi-stage auto-issuance.
31
33
  /// Tests stage ID computation consistency and multi-stage claiming behavior.
@@ -55,8 +57,9 @@ contract REVAutoIssuanceFuzz_Local is TestBaseWorkflow {
55
57
 
56
58
  SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
57
59
  HOOK_STORE = new JB721TiersHookStore();
58
- EXAMPLE_HOOK =
59
- new JB721TiersHook(jbDirectory(), jbPermissions(), jbRulesets(), HOOK_STORE, jbSplits(), multisig());
60
+ EXAMPLE_HOOK = new JB721TiersHook(
61
+ jbDirectory(), jbPermissions(), jbPrices(), jbRulesets(), HOOK_STORE, jbSplits(), multisig()
62
+ );
60
63
  ADDRESS_REGISTRY = new JBAddressRegistry();
61
64
  HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
62
65
  PUBLISHER = new CTPublisher(jbDirectory(), jbPermissions(), FEE_PROJECT_ID, multisig());
@@ -135,14 +138,16 @@ contract REVAutoIssuanceFuzz_Local is TestBaseWorkflow {
135
138
  });
136
139
 
137
140
  vm.prank(multisig());
138
- revnetId = REV_DEPLOYER.deployFor({
141
+ (revnetId,) = REV_DEPLOYER.deployFor({
139
142
  revnetId: 0,
140
143
  configuration: config,
141
144
  terminalConfigurations: terminalConfigs,
142
145
  suckerDeploymentConfiguration: REVSuckerDeploymentConfig({
143
146
  deployerConfigurations: new JBSuckerDeployerConfig[](0),
144
147
  salt: keccak256(abi.encodePacked("AUTOISSUE", numStages))
145
- })
148
+ }),
149
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
150
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
146
151
  });
147
152
  }
148
153
 
@@ -7,6 +7,8 @@ import /* {*} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
7
7
  import /* {*} from */ "./../src/REVDeployer.sol";
8
8
  import "@croptop/core-v6/src/CTPublisher.sol";
9
9
  import {MockBuybackDataHook} from "./mock/MockBuybackDataHook.sol";
10
+ import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
11
+ import {REVCroptopAllowedPost} from "../src/structs/REVCroptopAllowedPost.sol";
10
12
 
11
13
  import "@bananapus/core-v6/script/helpers/CoreDeploymentLib.sol";
12
14
  import "@bananapus/721-hook-v6/script/helpers/Hook721DeploymentLib.sol";
@@ -56,8 +58,9 @@ contract REVDeployerRegressions is TestBaseWorkflow {
56
58
 
57
59
  SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
58
60
  HOOK_STORE = new JB721TiersHookStore();
59
- EXAMPLE_HOOK =
60
- new JB721TiersHook(jbDirectory(), jbPermissions(), jbRulesets(), HOOK_STORE, jbSplits(), multisig());
61
+ EXAMPLE_HOOK = new JB721TiersHook(
62
+ jbDirectory(), jbPermissions(), jbPrices(), jbRulesets(), HOOK_STORE, jbSplits(), multisig()
63
+ );
61
64
  ADDRESS_REGISTRY = new JBAddressRegistry();
62
65
  HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
63
66
  PUBLISHER = new CTPublisher(jbDirectory(), jbPermissions(), FEE_PROJECT_ID, multisig());
@@ -174,13 +177,15 @@ contract REVDeployerRegressions is TestBaseWorkflow {
174
177
  });
175
178
 
176
179
  vm.prank(multisig());
177
- uint256 revnetId = REV_DEPLOYER.deployFor({
180
+ (uint256 revnetId,) = REV_DEPLOYER.deployFor({
178
181
  revnetId: FEE_PROJECT_ID,
179
182
  configuration: revnetConfiguration,
180
183
  terminalConfigurations: terminalConfigurations,
181
184
  suckerDeploymentConfiguration: REVSuckerDeploymentConfig({
182
185
  deployerConfigurations: new JBSuckerDeployerConfig[](0), salt: keccak256("C4_TEST")
183
- })
186
+ }),
187
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
188
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
184
189
  });
185
190
 
186
191
  // hasMintPermissionFor should return false for random addresses
@@ -283,13 +288,15 @@ contract REVDeployerRegressions is TestBaseWorkflow {
283
288
  });
284
289
 
285
290
  vm.prank(multisig());
286
- uint256 revnetId = REV_DEPLOYER.deployFor({
291
+ (uint256 revnetId,) = REV_DEPLOYER.deployFor({
287
292
  revnetId: 0,
288
293
  configuration: revnetConfiguration,
289
294
  terminalConfigurations: terminalConfigurations,
290
295
  suckerDeploymentConfiguration: REVSuckerDeploymentConfig({
291
296
  deployerConfigurations: new JBSuckerDeployerConfig[](0), salt: keccak256("H5_TEST")
292
- })
297
+ }),
298
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
299
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
293
300
  });
294
301
 
295
302
  // Verify the revnet was deployed
@@ -40,6 +40,8 @@ import {mulDiv} from "@prb/math/src/Common.sol";
40
40
 
41
41
  import {REVInvincibilityHandler} from "./REVInvincibilityHandler.sol";
42
42
  import {BrokenFeeTerminal} from "./helpers/MaliciousContracts.sol";
43
+ import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
44
+ import {REVCroptopAllowedPost} from "../src/structs/REVCroptopAllowedPost.sol";
43
45
 
44
46
  // =========================================================================
45
47
  // Shared config struct
@@ -202,8 +204,9 @@ contract REVInvincibility_PropertyTests is TestBaseWorkflow {
202
204
 
203
205
  SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
204
206
  HOOK_STORE = new JB721TiersHookStore();
205
- EXAMPLE_HOOK =
206
- new JB721TiersHook(jbDirectory(), jbPermissions(), jbRulesets(), HOOK_STORE, jbSplits(), multisig());
207
+ EXAMPLE_HOOK = new JB721TiersHook(
208
+ jbDirectory(), jbPermissions(), jbPrices(), jbRulesets(), HOOK_STORE, jbSplits(), multisig()
209
+ );
207
210
  ADDRESS_REGISTRY = new JBAddressRegistry();
208
211
  HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
209
212
  PUBLISHER = new CTPublisher(jbDirectory(), jbPermissions(), FEE_PROJECT_ID, multisig());
@@ -240,16 +243,20 @@ contract REVInvincibility_PropertyTests is TestBaseWorkflow {
240
243
  revnetId: FEE_PROJECT_ID,
241
244
  configuration: feeConfig.configuration,
242
245
  terminalConfigurations: feeConfig.terminalConfigurations,
243
- suckerDeploymentConfiguration: feeConfig.suckerDeploymentConfiguration
246
+ suckerDeploymentConfiguration: feeConfig.suckerDeploymentConfiguration,
247
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
248
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
244
249
  });
245
250
 
246
251
  // Deploy second revnet with loans
247
252
  InvincibilityProjectConfig memory revConfig = _getRevnetConfig();
248
- REVNET_ID = REV_DEPLOYER.deployFor({
253
+ (REVNET_ID,) = REV_DEPLOYER.deployFor({
249
254
  revnetId: 0,
250
255
  configuration: revConfig.configuration,
251
256
  terminalConfigurations: revConfig.terminalConfigurations,
252
- suckerDeploymentConfiguration: revConfig.suckerDeploymentConfiguration
257
+ suckerDeploymentConfiguration: revConfig.suckerDeploymentConfiguration,
258
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
259
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
253
260
  });
254
261
 
255
262
  vm.deal(USER, 10_000e18);
@@ -480,7 +487,7 @@ contract REVInvincibility_PropertyTests is TestBaseWorkflow {
480
487
  });
481
488
 
482
489
  vm.prank(multisig());
483
- uint256 h5RevnetId = REV_DEPLOYER.deployFor({
490
+ (uint256 h5RevnetId,) = REV_DEPLOYER.deployFor({
484
491
  revnetId: 0,
485
492
  configuration: REVConfig({
486
493
  description: REVDescription("H5Test", "H5T", "ipfs://h5", "H5_TOKEN"),
@@ -491,7 +498,9 @@ contract REVInvincibility_PropertyTests is TestBaseWorkflow {
491
498
  terminalConfigurations: tc,
492
499
  suckerDeploymentConfiguration: REVSuckerDeploymentConfig({
493
500
  deployerConfigurations: new JBSuckerDeployerConfig[](0), salt: keccak256("H5_INVINCIBILITY")
494
- })
501
+ }),
502
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
503
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
495
504
  });
496
505
 
497
506
  // Stage 0 auto-issuance stored at block.timestamp
@@ -953,8 +962,9 @@ contract REVInvincibility_Invariants is StdInvariant, TestBaseWorkflow {
953
962
 
954
963
  SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
955
964
  HOOK_STORE = new JB721TiersHookStore();
956
- EXAMPLE_HOOK =
957
- new JB721TiersHook(jbDirectory(), jbPermissions(), jbRulesets(), HOOK_STORE, jbSplits(), multisig());
965
+ EXAMPLE_HOOK = new JB721TiersHook(
966
+ jbDirectory(), jbPermissions(), jbPrices(), jbRulesets(), HOOK_STORE, jbSplits(), multisig()
967
+ );
958
968
  ADDRESS_REGISTRY = new JBAddressRegistry();
959
969
  HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
960
970
  PUBLISHER = new CTPublisher(jbDirectory(), jbPermissions(), FEE_PROJECT_ID, multisig());
@@ -1026,7 +1036,9 @@ contract REVInvincibility_Invariants is StdInvariant, TestBaseWorkflow {
1026
1036
  terminalConfigurations: tc,
1027
1037
  suckerDeploymentConfiguration: REVSuckerDeploymentConfig({
1028
1038
  deployerConfigurations: new JBSuckerDeployerConfig[](0), salt: keccak256("REV_INV")
1029
- })
1039
+ }),
1040
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
1041
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
1030
1042
  });
1031
1043
  }
1032
1044
 
@@ -1087,7 +1099,7 @@ contract REVInvincibility_Invariants is StdInvariant, TestBaseWorkflow {
1087
1099
  extraMetadata: 0
1088
1100
  });
1089
1101
 
1090
- REVNET_ID = REV_DEPLOYER.deployFor({
1102
+ (REVNET_ID,) = REV_DEPLOYER.deployFor({
1091
1103
  revnetId: 0,
1092
1104
  configuration: REVConfig({
1093
1105
  description: REVDescription("NANA", "$NANA", "ipfs://nana", "NANA_TOKEN_INV"),
@@ -1098,7 +1110,9 @@ contract REVInvincibility_Invariants is StdInvariant, TestBaseWorkflow {
1098
1110
  terminalConfigurations: tc,
1099
1111
  suckerDeploymentConfiguration: REVSuckerDeploymentConfig({
1100
1112
  deployerConfigurations: new JBSuckerDeployerConfig[](0), salt: keccak256("NANA_INV")
1101
- })
1113
+ }),
1114
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
1115
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
1102
1116
  });
1103
1117
  }
1104
1118
 
@@ -28,6 +28,8 @@ import {JB721TiersHook} from "@bananapus/721-hook-v6/src/JB721TiersHook.sol";
28
28
  import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
29
29
  import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
30
30
  import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
31
+ import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
32
+ import {REVCroptopAllowedPost} from "../src/structs/REVCroptopAllowedPost.sol";
31
33
 
32
34
  /// @notice Full revnet lifecycle E2E: deploy 3-stage -> pay -> advance stages -> cash out.
33
35
  contract REVLifecycle_Local is TestBaseWorkflow {
@@ -61,8 +63,9 @@ contract REVLifecycle_Local is TestBaseWorkflow {
61
63
 
62
64
  SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
63
65
  HOOK_STORE = new JB721TiersHookStore();
64
- EXAMPLE_HOOK =
65
- new JB721TiersHook(jbDirectory(), jbPermissions(), jbRulesets(), HOOK_STORE, jbSplits(), multisig());
66
+ EXAMPLE_HOOK = new JB721TiersHook(
67
+ jbDirectory(), jbPermissions(), jbPrices(), jbRulesets(), HOOK_STORE, jbSplits(), multisig()
68
+ );
66
69
  ADDRESS_REGISTRY = new JBAddressRegistry();
67
70
  HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
68
71
  PUBLISHER = new CTPublisher(jbDirectory(), jbPermissions(), FEE_PROJECT_ID, multisig());
@@ -162,13 +165,15 @@ contract REVLifecycle_Local is TestBaseWorkflow {
162
165
  });
163
166
 
164
167
  vm.prank(multisig());
165
- REVNET_ID = REV_DEPLOYER.deployFor({
168
+ (REVNET_ID,) = REV_DEPLOYER.deployFor({
166
169
  revnetId: FEE_PROJECT_ID,
167
170
  configuration: revnetConfiguration,
168
171
  terminalConfigurations: terminalConfigurations,
169
172
  suckerDeploymentConfiguration: REVSuckerDeploymentConfig({
170
173
  deployerConfigurations: new JBSuckerDeployerConfig[](0), salt: keccak256("LIFECYCLE_TEST")
171
- })
174
+ }),
175
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
176
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
172
177
  });
173
178
  }
174
179
 
@@ -9,6 +9,8 @@ import /* {*} from */ "./../src/REVDeployer.sol";
9
9
  import /* {*} from */ "./../src/REVLoans.sol";
10
10
  import "@croptop/core-v6/src/CTPublisher.sol";
11
11
  import {MockBuybackDataHook} from "./mock/MockBuybackDataHook.sol";
12
+ import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
13
+ import {REVCroptopAllowedPost} from "../src/structs/REVCroptopAllowedPost.sol";
12
14
 
13
15
  import "@bananapus/core-v6/script/helpers/CoreDeploymentLib.sol";
14
16
  import "@bananapus/721-hook-v6/script/helpers/Hook721DeploymentLib.sol";
@@ -476,8 +478,9 @@ contract InvariantREVLoansTests is StdInvariant, TestBaseWorkflow {
476
478
 
477
479
  HOOK_STORE = new JB721TiersHookStore();
478
480
 
479
- EXAMPLE_HOOK =
480
- new JB721TiersHook(jbDirectory(), jbPermissions(), jbRulesets(), HOOK_STORE, jbSplits(), multisig());
481
+ EXAMPLE_HOOK = new JB721TiersHook(
482
+ jbDirectory(), jbPermissions(), jbPrices(), jbRulesets(), HOOK_STORE, jbSplits(), multisig()
483
+ );
481
484
 
482
485
  ADDRESS_REGISTRY = new JBAddressRegistry();
483
486
 
@@ -515,22 +518,26 @@ contract InvariantREVLoansTests is StdInvariant, TestBaseWorkflow {
515
518
 
516
519
  // Configure the project.
517
520
  vm.prank(address(multisig()));
518
- REVNET_ID = REV_DEPLOYER.deployFor({
521
+ (REVNET_ID,) = REV_DEPLOYER.deployFor({
519
522
  revnetId: FEE_PROJECT_ID, // Zero to deploy a new revnet
520
523
  configuration: feeProjectConfig.configuration,
521
524
  terminalConfigurations: feeProjectConfig.terminalConfigurations,
522
- suckerDeploymentConfiguration: feeProjectConfig.suckerDeploymentConfiguration
525
+ suckerDeploymentConfiguration: feeProjectConfig.suckerDeploymentConfiguration,
526
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
527
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
523
528
  });
524
529
 
525
530
  // Configure second revnet
526
531
  FeeProjectConfig memory fee2Config = getSecondProjectConfig();
527
532
 
528
533
  // Configure the second project.
529
- REVNET_ID = REV_DEPLOYER.deployFor({
534
+ (REVNET_ID,) = REV_DEPLOYER.deployFor({
530
535
  revnetId: 0, // Zero to deploy a new revnet
531
536
  configuration: fee2Config.configuration,
532
537
  terminalConfigurations: fee2Config.terminalConfigurations,
533
- suckerDeploymentConfiguration: fee2Config.suckerDeploymentConfiguration
538
+ suckerDeploymentConfiguration: fee2Config.suckerDeploymentConfiguration,
539
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
540
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
534
541
  });
535
542
 
536
543
  INITIAL_TIMESTAMP = block.timestamp;
@@ -31,6 +31,8 @@ import {JB721TiersHook} from "@bananapus/721-hook-v6/src/JB721TiersHook.sol";
31
31
  import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
32
32
  import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
33
33
  import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
34
+ import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
35
+ import {REVCroptopAllowedPost} from "../src/structs/REVCroptopAllowedPost.sol";
34
36
  import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
35
37
  import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
36
38
 
@@ -318,8 +320,9 @@ contract REVLoansAttacks is TestBaseWorkflow {
318
320
 
319
321
  SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
320
322
  HOOK_STORE = new JB721TiersHookStore();
321
- EXAMPLE_HOOK =
322
- new JB721TiersHook(jbDirectory(), jbPermissions(), jbRulesets(), HOOK_STORE, jbSplits(), multisig());
323
+ EXAMPLE_HOOK = new JB721TiersHook(
324
+ jbDirectory(), jbPermissions(), jbPrices(), jbRulesets(), HOOK_STORE, jbSplits(), multisig()
325
+ );
323
326
  ADDRESS_REGISTRY = new JBAddressRegistry();
324
327
  HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
325
328
  PUBLISHER = new CTPublisher(jbDirectory(), jbPermissions(), FEE_PROJECT_ID, multisig());
@@ -361,16 +364,20 @@ contract REVLoansAttacks is TestBaseWorkflow {
361
364
  revnetId: FEE_PROJECT_ID,
362
365
  configuration: feeProjectConfig.configuration,
363
366
  terminalConfigurations: feeProjectConfig.terminalConfigurations,
364
- suckerDeploymentConfiguration: feeProjectConfig.suckerDeploymentConfiguration
367
+ suckerDeploymentConfiguration: feeProjectConfig.suckerDeploymentConfiguration,
368
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
369
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
365
370
  });
366
371
 
367
372
  // Deploy second revnet with loans enabled
368
373
  AttackProjectConfig memory revnetConfig = _getRevnetConfig();
369
- REVNET_ID = REV_DEPLOYER.deployFor({
374
+ (REVNET_ID,) = REV_DEPLOYER.deployFor({
370
375
  revnetId: 0,
371
376
  configuration: revnetConfig.configuration,
372
377
  terminalConfigurations: revnetConfig.terminalConfigurations,
373
- suckerDeploymentConfiguration: revnetConfig.suckerDeploymentConfiguration
378
+ suckerDeploymentConfiguration: revnetConfig.suckerDeploymentConfiguration,
379
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
380
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
374
381
  });
375
382
 
376
383
  vm.deal(USER, 1000e18);
@@ -34,6 +34,8 @@ import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressReg
34
34
  import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
35
35
  import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
36
36
  import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
37
+ import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
38
+ import {REVCroptopAllowedPost} from "../src/structs/REVCroptopAllowedPost.sol";
37
39
 
38
40
  /// @notice A terminal mock that always reverts on pay(), used to simulate fee payment failure.
39
41
  contract RevertingFeeTerminal is ERC165, IJBPayoutTerminal {
@@ -279,8 +281,9 @@ contract REVLoansFeeRecovery is TestBaseWorkflow {
279
281
 
280
282
  SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
281
283
  HOOK_STORE = new JB721TiersHookStore();
282
- EXAMPLE_HOOK =
283
- new JB721TiersHook(jbDirectory(), jbPermissions(), jbRulesets(), HOOK_STORE, jbSplits(), multisig());
284
+ EXAMPLE_HOOK = new JB721TiersHook(
285
+ jbDirectory(), jbPermissions(), jbPrices(), jbRulesets(), HOOK_STORE, jbSplits(), multisig()
286
+ );
284
287
  ADDRESS_REGISTRY = new JBAddressRegistry();
285
288
  HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
286
289
  PUBLISHER = new CTPublisher(jbDirectory(), jbPermissions(), FEE_PROJECT_ID, multisig());
@@ -323,16 +326,20 @@ contract REVLoansFeeRecovery is TestBaseWorkflow {
323
326
  revnetId: FEE_PROJECT_ID,
324
327
  configuration: feeProjectConfig.configuration,
325
328
  terminalConfigurations: feeProjectConfig.terminalConfigurations,
326
- suckerDeploymentConfiguration: feeProjectConfig.suckerDeploymentConfiguration
329
+ suckerDeploymentConfiguration: feeProjectConfig.suckerDeploymentConfiguration,
330
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
331
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
327
332
  });
328
333
 
329
334
  // Deploy revnet with loans enabled.
330
335
  FeeRecoveryProjectConfig memory revnetConfig = _getRevnetConfig();
331
- REVNET_ID = REV_DEPLOYER.deployFor({
336
+ (REVNET_ID,) = REV_DEPLOYER.deployFor({
332
337
  revnetId: 0,
333
338
  configuration: revnetConfig.configuration,
334
339
  terminalConfigurations: revnetConfig.terminalConfigurations,
335
- suckerDeploymentConfiguration: revnetConfig.suckerDeploymentConfiguration
340
+ suckerDeploymentConfiguration: revnetConfig.suckerDeploymentConfiguration,
341
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
342
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
336
343
  });
337
344
 
338
345
  vm.deal(USER, 1000e18);
@@ -34,6 +34,8 @@ import {JB721TiersHook} from "@bananapus/721-hook-v6/src/JB721TiersHook.sol";
34
34
  import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
35
35
  import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
36
36
  import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
37
+ import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
38
+ import {REVCroptopAllowedPost} from "../src/structs/REVCroptopAllowedPost.sol";
37
39
 
38
40
  /// @notice A fake terminal that returns garbage accounting contexts.
39
41
  /// Used to test unvalidated loan source terminal rejection.
@@ -162,8 +164,9 @@ contract REVLoansFindings is TestBaseWorkflow {
162
164
 
163
165
  SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
164
166
  HOOK_STORE = new JB721TiersHookStore();
165
- EXAMPLE_HOOK =
166
- new JB721TiersHook(jbDirectory(), jbPermissions(), jbRulesets(), HOOK_STORE, jbSplits(), multisig());
167
+ EXAMPLE_HOOK = new JB721TiersHook(
168
+ jbDirectory(), jbPermissions(), jbPrices(), jbRulesets(), HOOK_STORE, jbSplits(), multisig()
169
+ );
167
170
  ADDRESS_REGISTRY = new JBAddressRegistry();
168
171
  HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
169
172
  PUBLISHER = new CTPublisher(jbDirectory(), jbPermissions(), FEE_PROJECT_ID, multisig());
@@ -247,7 +250,9 @@ contract REVLoansFindings is TestBaseWorkflow {
247
250
  terminalConfigurations: terminalConfigurations,
248
251
  suckerDeploymentConfiguration: REVSuckerDeploymentConfig({
249
252
  deployerConfigurations: new JBSuckerDeployerConfig[](0), salt: keccak256(abi.encodePacked("REV"))
250
- })
253
+ }),
254
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
255
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
251
256
  });
252
257
  }
253
258
 
@@ -285,13 +290,15 @@ contract REVLoansFindings is TestBaseWorkflow {
285
290
  stageConfigurations: stageConfigurations
286
291
  });
287
292
 
288
- REVNET_ID = REV_DEPLOYER.deployFor({
293
+ (REVNET_ID,) = REV_DEPLOYER.deployFor({
289
294
  revnetId: 0,
290
295
  configuration: revnetConfiguration,
291
296
  terminalConfigurations: terminalConfigurations,
292
297
  suckerDeploymentConfiguration: REVSuckerDeploymentConfig({
293
298
  deployerConfigurations: new JBSuckerDeployerConfig[](0), salt: keccak256(abi.encodePacked("BRW"))
294
- })
299
+ }),
300
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
301
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
295
302
  });
296
303
  }
297
304
 
@@ -519,13 +526,15 @@ contract REVLoansFindings is TestBaseWorkflow {
519
526
  // Record the deploy timestamp -- this is used for stage ID calculation.
520
527
  uint256 deployTimestamp = block.timestamp;
521
528
 
522
- uint256 fp1RevnetId = REV_DEPLOYER.deployFor({
529
+ (uint256 fp1RevnetId,) = REV_DEPLOYER.deployFor({
523
530
  revnetId: 0,
524
531
  configuration: config,
525
532
  terminalConfigurations: terminalConfigurations,
526
533
  suckerDeploymentConfiguration: REVSuckerDeploymentConfig({
527
534
  deployerConfigurations: new JBSuckerDeployerConfig[](0), salt: keccak256("FP1")
528
- })
535
+ }),
536
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
537
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
529
538
  });
530
539
 
531
540
  // Step 2: Verify the second ruleset ID matches deployTimestamp + 1.
@@ -30,6 +30,8 @@ import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStor
30
30
  import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
31
31
  import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
32
32
  import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
33
+ import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
34
+ import {REVCroptopAllowedPost} from "../src/structs/REVCroptopAllowedPost.sol";
33
35
 
34
36
  /// @notice A fake terminal that tracks whether useAllowanceOf was called.
35
37
  /// @dev REVLoans.borrowFrom does not validate source terminal registration.
@@ -157,8 +159,9 @@ contract REVLoansRegressions is TestBaseWorkflow {
157
159
 
158
160
  SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
159
161
  HOOK_STORE = new JB721TiersHookStore();
160
- EXAMPLE_HOOK =
161
- new JB721TiersHook(jbDirectory(), jbPermissions(), jbRulesets(), HOOK_STORE, jbSplits(), multisig());
162
+ EXAMPLE_HOOK = new JB721TiersHook(
163
+ jbDirectory(), jbPermissions(), jbPrices(), jbRulesets(), HOOK_STORE, jbSplits(), multisig()
164
+ );
162
165
  ADDRESS_REGISTRY = new JBAddressRegistry();
163
166
  HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
164
167
  PUBLISHER = new CTPublisher(jbDirectory(), jbPermissions(), FEE_PROJECT_ID, multisig());
@@ -229,13 +232,15 @@ contract REVLoansRegressions is TestBaseWorkflow {
229
232
  });
230
233
 
231
234
  vm.prank(multisig());
232
- REVNET_ID = REV_DEPLOYER.deployFor({
235
+ (REVNET_ID,) = REV_DEPLOYER.deployFor({
233
236
  revnetId: FEE_PROJECT_ID,
234
237
  configuration: revnetConfiguration,
235
238
  terminalConfigurations: terminalConfigurations,
236
239
  suckerDeploymentConfiguration: REVSuckerDeploymentConfig({
237
240
  deployerConfigurations: new JBSuckerDeployerConfig[](0), salt: keccak256("H6_TEST")
238
- })
241
+ }),
242
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
243
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
239
244
  });
240
245
  }
241
246