@rev-net/core-v6 0.0.11 → 0.0.13

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 (81) hide show
  1. package/ADMINISTRATION.md +7 -7
  2. package/ARCHITECTURE.md +11 -11
  3. package/AUDIT_INSTRUCTIONS.md +295 -0
  4. package/CHANGE_LOG.md +316 -0
  5. package/README.md +9 -6
  6. package/RISKS.md +180 -35
  7. package/SKILLS.md +9 -11
  8. package/STYLE_GUIDE.md +14 -1
  9. package/USER_JOURNEYS.md +489 -0
  10. package/package.json +9 -9
  11. package/script/Deploy.s.sol +124 -40
  12. package/script/helpers/RevnetCoreDeploymentLib.sol +19 -6
  13. package/src/REVDeployer.sol +183 -175
  14. package/src/REVLoans.sol +65 -28
  15. package/src/interfaces/IREVDeployer.sol +25 -23
  16. package/src/structs/REV721TiersHookFlags.sol +1 -0
  17. package/src/structs/REVAutoIssuance.sol +1 -0
  18. package/src/structs/REVBaseline721HookConfig.sol +1 -0
  19. package/src/structs/REVConfig.sol +1 -0
  20. package/src/structs/REVCroptopAllowedPost.sol +1 -0
  21. package/src/structs/REVDeploy721TiersHookConfig.sol +13 -14
  22. package/src/structs/REVDescription.sol +1 -0
  23. package/src/structs/REVLoan.sol +1 -0
  24. package/src/structs/REVLoanSource.sol +1 -0
  25. package/src/structs/REVStageConfig.sol +1 -0
  26. package/src/structs/REVSuckerDeploymentConfig.sol +1 -0
  27. package/test/REV.integrations.t.sol +148 -19
  28. package/test/REVAutoIssuanceFuzz.t.sol +31 -6
  29. package/test/REVDeployerRegressions.t.sol +47 -9
  30. package/test/REVInvincibility.t.sol +83 -19
  31. package/test/REVInvincibilityHandler.sol +29 -0
  32. package/test/REVLifecycle.t.sol +36 -6
  33. package/test/REVLoans.invariants.t.sol +64 -10
  34. package/test/REVLoansAttacks.t.sol +54 -9
  35. package/test/REVLoansFeeRecovery.t.sol +61 -15
  36. package/test/REVLoansFindings.t.sol +42 -9
  37. package/test/REVLoansRegressions.t.sol +33 -6
  38. package/test/REVLoansSourceFeeRecovery.t.sol +491 -0
  39. package/test/REVLoansSourced.t.sol +79 -17
  40. package/test/REVLoansUnSourced.t.sol +61 -10
  41. package/test/TestBurnHeldTokens.t.sol +47 -11
  42. package/test/TestCEIPattern.t.sol +37 -6
  43. package/test/TestCashOutCallerValidation.t.sol +41 -8
  44. package/test/TestConversionDocumentation.t.sol +50 -13
  45. package/test/TestCrossCurrencyReclaim.t.sol +584 -0
  46. package/test/TestCrossSourceReallocation.t.sol +37 -6
  47. package/test/TestERC2771MetaTx.t.sol +557 -0
  48. package/test/TestEmptyBuybackSpecs.t.sol +45 -10
  49. package/test/TestFlashLoanSurplus.t.sol +39 -7
  50. package/test/TestHookArrayOOB.t.sol +42 -13
  51. package/test/TestLiquidationBehavior.t.sol +37 -7
  52. package/test/TestLoanSourceRotation.t.sol +525 -0
  53. package/test/TestLongTailEconomics.t.sol +651 -0
  54. package/test/TestLowFindings.t.sol +80 -8
  55. package/test/TestMixedFixes.t.sol +43 -9
  56. package/test/TestPermit2Signatures.t.sol +657 -0
  57. package/test/TestReallocationSandwich.t.sol +384 -0
  58. package/test/TestRevnetRegressions.t.sol +324 -0
  59. package/test/TestSplitWeightAdjustment.t.sol +52 -13
  60. package/test/TestSplitWeightE2E.t.sol +53 -18
  61. package/test/TestSplitWeightFork.t.sol +66 -21
  62. package/test/TestStageTransitionBorrowable.t.sol +38 -6
  63. package/test/TestSwapTerminalPermission.t.sol +37 -7
  64. package/test/TestUint112Overflow.t.sol +39 -6
  65. package/test/TestZeroRepayment.t.sol +37 -6
  66. package/test/fork/ForkTestBase.sol +66 -17
  67. package/test/fork/TestCashOutFork.t.sol +9 -3
  68. package/test/fork/TestLoanBorrowFork.t.sol +1 -0
  69. package/test/fork/TestLoanCrossRulesetFork.t.sol +11 -3
  70. package/test/fork/TestLoanLiquidationFork.t.sol +1 -0
  71. package/test/fork/TestLoanReallocateFork.t.sol +1 -0
  72. package/test/fork/TestLoanRepayFork.t.sol +1 -0
  73. package/test/fork/TestLoanTransferFork.t.sol +133 -0
  74. package/test/fork/TestSplitWeightFork.t.sol +3 -0
  75. package/test/helpers/REVEmpty721Config.sol +46 -0
  76. package/test/mock/MockBuybackDataHook.sol +1 -0
  77. package/test/regression/TestBurnPermissionRequired.t.sol +267 -0
  78. package/test/regression/TestCrossRevnetLiquidation.t.sol +228 -0
  79. package/test/regression/TestCumulativeLoanCounter.t.sol +38 -8
  80. package/test/regression/TestLiquidateGapHandling.t.sol +40 -8
  81. package/test/regression/TestZeroPriceFeed.t.sol +396 -0
@@ -1,17 +1,26 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  pragma solidity 0.8.26;
3
3
 
4
+ // forge-lint: disable-next-line(unaliased-plain-import)
4
5
  import "forge-std/Test.sol";
6
+ // forge-lint: disable-next-line(unaliased-plain-import)
5
7
  import /* {*} from */ "@bananapus/core-v6/test/helpers/TestBaseWorkflow.sol";
6
- import /* {*} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
8
+ // import /* {*} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
9
+ // forge-lint: disable-next-line(unaliased-plain-import)
7
10
  import /* {*} from */ "./../src/REVDeployer.sol";
11
+ // forge-lint: disable-next-line(unaliased-plain-import)
8
12
  import "@croptop/core-v6/src/CTPublisher.sol";
9
13
  import {MockBuybackDataHook} from "./mock/MockBuybackDataHook.sol";
10
14
 
15
+ // forge-lint: disable-next-line(unaliased-plain-import)
11
16
  import "@bananapus/core-v6/script/helpers/CoreDeploymentLib.sol";
17
+ // forge-lint: disable-next-line(unaliased-plain-import)
12
18
  import "@bananapus/721-hook-v6/script/helpers/Hook721DeploymentLib.sol";
19
+ // forge-lint: disable-next-line(unaliased-plain-import)
13
20
  import "@bananapus/suckers-v6/script/helpers/SuckerDeploymentLib.sol";
21
+ // forge-lint: disable-next-line(unaliased-plain-import)
14
22
  import "@croptop/core-v6/script/helpers/CroptopDeploymentLib.sol";
23
+ // forge-lint: disable-next-line(unaliased-plain-import)
15
24
  import "@bananapus/router-terminal-v6/script/helpers/RouterTerminalDeploymentLib.sol";
16
25
 
17
26
  import {JBConstants} from "@bananapus/core-v6/src/libraries/JBConstants.sol";
@@ -31,6 +40,7 @@ import {JB721TiersHook} from "@bananapus/721-hook-v6/src/JB721TiersHook.sol";
31
40
  import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
32
41
  import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
33
42
  import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
43
+ import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
34
44
 
35
45
  struct FeeProjectConfig {
36
46
  REVConfig configuration;
@@ -40,30 +50,45 @@ struct FeeProjectConfig {
40
50
 
41
51
  contract REVLoansSourcedTests is TestBaseWorkflow {
42
52
  /// @notice the salts that are used to deploy the contracts.
53
+ // forge-lint: disable-next-line(mixed-case-variable)
43
54
  bytes32 REV_DEPLOYER_SALT = "REVDeployer";
55
+ // forge-lint: disable-next-line(mixed-case-variable)
44
56
  bytes32 ERC20_SALT = "REV_TOKEN";
45
57
 
58
+ // forge-lint: disable-next-line(mixed-case-variable)
46
59
  REVDeployer REV_DEPLOYER;
60
+ // forge-lint: disable-next-line(mixed-case-variable)
47
61
  JB721TiersHook EXAMPLE_HOOK;
48
62
 
49
63
  /// @notice Deploys tiered ERC-721 hooks for revnets.
64
+ // forge-lint: disable-next-line(mixed-case-variable)
50
65
  IJB721TiersHookDeployer HOOK_DEPLOYER;
66
+ // forge-lint: disable-next-line(mixed-case-variable)
51
67
  IJB721TiersHookStore HOOK_STORE;
68
+ // forge-lint: disable-next-line(mixed-case-variable)
52
69
  IJBAddressRegistry ADDRESS_REGISTRY;
53
70
 
71
+ // forge-lint: disable-next-line(mixed-case-variable)
54
72
  IREVLoans LOANS_CONTRACT;
55
73
 
74
+ // forge-lint: disable-next-line(mixed-case-variable)
56
75
  MockERC20 TOKEN;
57
76
 
58
77
  /// @notice Deploys and tracks suckers for revnets.
78
+ // forge-lint: disable-next-line(mixed-case-variable)
59
79
  IJBSuckerRegistry SUCKER_REGISTRY;
60
80
 
81
+ // forge-lint: disable-next-line(mixed-case-variable)
61
82
  CTPublisher PUBLISHER;
83
+ // forge-lint: disable-next-line(mixed-case-variable)
62
84
  MockBuybackDataHook MOCK_BUYBACK;
63
85
 
86
+ // forge-lint: disable-next-line(mixed-case-variable)
64
87
  uint256 FEE_PROJECT_ID;
88
+ // forge-lint: disable-next-line(mixed-case-variable)
65
89
  uint256 REVNET_ID;
66
90
 
91
+ // forge-lint: disable-next-line(mixed-case-variable)
67
92
  address USER = makeAddr("user");
68
93
 
69
94
  /// @notice The address that is allowed to forward calls.
@@ -105,7 +130,11 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
105
130
  {
106
131
  REVAutoIssuance[] memory issuanceConfs = new REVAutoIssuance[](1);
107
132
  issuanceConfs[0] = REVAutoIssuance({
108
- chainId: uint32(block.chainid), count: uint104(70_000 * decimalMultiplier), beneficiary: multisig()
133
+ // forge-lint: disable-next-line(unsafe-typecast)
134
+ chainId: uint32(block.chainid),
135
+ // forge-lint: disable-next-line(unsafe-typecast)
136
+ count: uint104(70_000 * decimalMultiplier),
137
+ beneficiary: multisig()
109
138
  });
110
139
 
111
140
  stageConfigurations[0] = REVStageConfig({
@@ -113,6 +142,7 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
113
142
  autoIssuances: issuanceConfs,
114
143
  splitPercent: 2000, // 20%
115
144
  splits: splits,
145
+ // forge-lint: disable-next-line(unsafe-typecast)
116
146
  initialIssuance: uint112(1000 * decimalMultiplier),
117
147
  issuanceCutFrequency: 90 days,
118
148
  issuanceCutPercent: JBConstants.MAX_WEIGHT_CUT_PERCENT / 2,
@@ -147,6 +177,7 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
147
177
 
148
178
  // The project's revnet configuration
149
179
  REVConfig memory revnetConfiguration = REVConfig({
180
+ // forge-lint: disable-next-line(named-struct-fields)
150
181
  description: REVDescription(name, symbol, projectUri, ERC20_SALT),
151
182
  baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
152
183
  splitOperator: multisig(),
@@ -196,7 +227,11 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
196
227
  {
197
228
  REVAutoIssuance[] memory issuanceConfs = new REVAutoIssuance[](1);
198
229
  issuanceConfs[0] = REVAutoIssuance({
199
- chainId: uint32(block.chainid), count: uint104(70_000 * decimalMultiplier), beneficiary: multisig()
230
+ // forge-lint: disable-next-line(unsafe-typecast)
231
+ chainId: uint32(block.chainid),
232
+ // forge-lint: disable-next-line(unsafe-typecast)
233
+ count: uint104(70_000 * decimalMultiplier),
234
+ beneficiary: multisig()
200
235
  });
201
236
 
202
237
  stageConfigurations[0] = REVStageConfig({
@@ -204,6 +239,7 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
204
239
  autoIssuances: issuanceConfs,
205
240
  splitPercent: 2000, // 20%
206
241
  splits: splits,
242
+ // forge-lint: disable-next-line(unsafe-typecast)
207
243
  initialIssuance: uint112(1000 * decimalMultiplier),
208
244
  issuanceCutFrequency: 90 days,
209
245
  issuanceCutPercent: JBConstants.MAX_WEIGHT_CUT_PERCENT / 2,
@@ -238,6 +274,7 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
238
274
 
239
275
  // The project's revnet configuration
240
276
  REVConfig memory revnetConfiguration = REVConfig({
277
+ // forge-lint: disable-next-line(named-struct-fields)
241
278
  description: REVDescription(name, symbol, projectUri, "NANA_TOKEN"),
242
279
  baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
243
280
  splitOperator: multisig(),
@@ -262,8 +299,9 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
262
299
 
263
300
  HOOK_STORE = new JB721TiersHookStore();
264
301
 
265
- EXAMPLE_HOOK =
266
- new JB721TiersHook(jbDirectory(), jbPermissions(), jbRulesets(), HOOK_STORE, jbSplits(), multisig());
302
+ EXAMPLE_HOOK = new JB721TiersHook(
303
+ jbDirectory(), jbPermissions(), jbPrices(), jbRulesets(), HOOK_STORE, jbSplits(), multisig()
304
+ );
267
305
 
268
306
  ADDRESS_REGISTRY = new JBAddressRegistry();
269
307
 
@@ -317,18 +355,22 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
317
355
  revnetId: FEE_PROJECT_ID, // Zero to deploy a new revnet
318
356
  configuration: feeProjectConfig.configuration,
319
357
  terminalConfigurations: feeProjectConfig.terminalConfigurations,
320
- suckerDeploymentConfiguration: feeProjectConfig.suckerDeploymentConfiguration
358
+ suckerDeploymentConfiguration: feeProjectConfig.suckerDeploymentConfiguration,
359
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
360
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
321
361
  });
322
362
 
323
363
  // Configure second revnet
324
364
  FeeProjectConfig memory fee2Config = getSecondProjectConfig();
325
365
 
326
366
  // Configure the project.
327
- REVNET_ID = REV_DEPLOYER.deployFor({
367
+ (REVNET_ID,) = REV_DEPLOYER.deployFor({
328
368
  revnetId: 0, // Zero to deploy a new revnet
329
369
  configuration: fee2Config.configuration,
330
370
  terminalConfigurations: fee2Config.terminalConfigurations,
331
- suckerDeploymentConfiguration: fee2Config.suckerDeploymentConfiguration
371
+ suckerDeploymentConfiguration: fee2Config.suckerDeploymentConfiguration,
372
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
373
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
332
374
  });
333
375
 
334
376
  // Give Eth for the user experience
@@ -510,6 +552,7 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
510
552
  uint256 amountPaid = balanceBefore - TOKEN.balanceOf(USER);
511
553
 
512
554
  // We expect the fee to be 100% for the min prepaid with the max duration.
555
+ // forge-lint: disable-next-line(divide-before-multiply)
513
556
  uint256 expectedFee = (loan.amount * (1000 - prepaidFee) / 1000) * expectedFeePercent / 1000;
514
557
 
515
558
  // The fee may deviate 1%.
@@ -567,11 +610,14 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
567
610
  assertEq(TOKEN.balanceOf(address(LOANS_CONTRACT)), 0);
568
611
 
569
612
  // The fees to be paid to NANA.
613
+ // forge-lint: disable-next-line(mixed-case-variable)
570
614
  uint256 allowance_fees = JBFees.feeAmountFrom({amountBeforeFee: loanable, feePercent: jbMultiTerminal().FEE()});
571
615
  // The fees to be paid to REV.
616
+ // forge-lint: disable-next-line(mixed-case-variable)
572
617
  uint256 rev_fees =
573
618
  JBFees.feeAmountFrom({amountBeforeFee: loanable, feePercent: LOANS_CONTRACT.REV_PREPAID_FEE_PERCENT()});
574
619
  // The fees to be paid to the Project we are taking a loan from.
620
+ // forge-lint: disable-next-line(mixed-case-variable)
575
621
  uint256 source_fees = JBFees.feeAmountFrom({amountBeforeFee: loanable, feePercent: prepaidFee});
576
622
  uint256 fees = allowance_fees + rev_fees + source_fees;
577
623
 
@@ -631,11 +677,13 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
631
677
  projectConfig.configuration.stageConfigurations = stageConfigurations;
632
678
  projectConfig.configuration.description.salt = "FeeChange";
633
679
 
634
- revnetProjectId = REV_DEPLOYER.deployFor({
680
+ (revnetProjectId,) = REV_DEPLOYER.deployFor({
635
681
  revnetId: 0, // Zero to deploy a new revnet
636
682
  configuration: projectConfig.configuration,
637
683
  terminalConfigurations: projectConfig.terminalConfigurations,
638
- suckerDeploymentConfiguration: projectConfig.suckerDeploymentConfiguration
684
+ suckerDeploymentConfiguration: projectConfig.suckerDeploymentConfiguration,
685
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
686
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
639
687
  });
640
688
  }
641
689
 
@@ -661,7 +709,12 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
661
709
 
662
710
  // Check what a borrow would result in more.
663
711
  uint256 loanable = LOANS_CONTRACT.borrowableAmountFrom(
664
- revnetProjectId, tokensToCashout, useNative ? 18 : 6, uint32(uint160(token))
712
+ // forge-lint: disable-next-line(unsafe-typecast)
713
+ revnetProjectId,
714
+ tokensToCashout,
715
+ useNative ? 18 : 6,
716
+ // forge-lint: disable-next-line(unsafe-typecast)
717
+ uint32(uint160(token))
665
718
  );
666
719
 
667
720
  uint256 fullReclaimableSurplus = jbMultiTerminal().STORE()
@@ -1117,7 +1170,8 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
1117
1170
  if (premint > 0) {
1118
1171
  issuanceConfs = new REVAutoIssuance[](1);
1119
1172
  issuanceConfs[0] =
1120
- REVAutoIssuance({chainId: uint32(block.chainid), count: uint104(premint), beneficiary: multisig()});
1173
+ // forge-lint: disable-next-line(unsafe-typecast)
1174
+ REVAutoIssuance({chainId: uint32(block.chainid), count: uint104(premint), beneficiary: multisig()});
1121
1175
  }
1122
1176
 
1123
1177
  JBSplit[] memory splits = new JBSplit[](1);
@@ -1141,11 +1195,13 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
1141
1195
  projectConfig.configuration.stageConfigurations = stageConfigurations;
1142
1196
  projectConfig.configuration.description.salt = "FeeChange";
1143
1197
 
1144
- revnetProjectId = REV_DEPLOYER.deployFor({
1198
+ (revnetProjectId,) = REV_DEPLOYER.deployFor({
1145
1199
  revnetId: 0, // Zero to deploy a new revnet
1146
1200
  configuration: projectConfig.configuration,
1147
1201
  terminalConfigurations: projectConfig.terminalConfigurations,
1148
- suckerDeploymentConfiguration: projectConfig.suckerDeploymentConfiguration
1202
+ suckerDeploymentConfiguration: projectConfig.suckerDeploymentConfiguration,
1203
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
1204
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
1149
1205
  });
1150
1206
  }
1151
1207
 
@@ -1165,7 +1221,11 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
1165
1221
  permissionIds[0] = JBPermissionIds.BURN_TOKENS;
1166
1222
 
1167
1223
  JBPermissionsData memory permissionsData = JBPermissionsData({
1168
- operator: address(LOANS_CONTRACT), projectId: uint56(revnetProjectId), permissionIds: permissionIds
1224
+ // forge-lint: disable-next-line(unsafe-typecast)
1225
+ operator: address(LOANS_CONTRACT),
1226
+ // forge-lint: disable-next-line(unsafe-typecast)
1227
+ projectId: uint56(revnetProjectId),
1228
+ permissionIds: permissionIds
1169
1229
  });
1170
1230
 
1171
1231
  // Give the loans contract permission to our tokens.
@@ -1237,11 +1297,13 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
1237
1297
  projectConfig.configuration.stageConfigurations = stageConfigurations;
1238
1298
  projectConfig.configuration.description.salt = "FeeChange";
1239
1299
 
1240
- uint256 revnetProjectId = REV_DEPLOYER.deployFor({
1300
+ (uint256 revnetProjectId,) = REV_DEPLOYER.deployFor({
1241
1301
  revnetId: 0, // Zero to deploy a new revnet
1242
1302
  configuration: projectConfig.configuration,
1243
1303
  terminalConfigurations: projectConfig.terminalConfigurations,
1244
- suckerDeploymentConfiguration: projectConfig.suckerDeploymentConfiguration
1304
+ suckerDeploymentConfiguration: projectConfig.suckerDeploymentConfiguration,
1305
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
1306
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
1245
1307
  });
1246
1308
 
1247
1309
  vm.startPrank(USER);
@@ -1,17 +1,27 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  pragma solidity 0.8.26;
3
3
 
4
+ // forge-lint: disable-next-line(unaliased-plain-import)
4
5
  import "forge-std/Test.sol";
6
+ // forge-lint: disable-next-line(unaliased-plain-import)
5
7
  import /* {*} from */ "@bananapus/core-v6/test/helpers/TestBaseWorkflow.sol";
6
- import /* {*} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
8
+ // import /* {*} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
9
+ // forge-lint: disable-next-line(unaliased-plain-import)
7
10
  import /* {*} from */ "./../src/REVDeployer.sol";
11
+ // forge-lint: disable-next-line(unaliased-plain-import)
8
12
  import "@croptop/core-v6/src/CTPublisher.sol";
9
13
  import {MockBuybackDataHook} from "./mock/MockBuybackDataHook.sol";
14
+ import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
10
15
 
16
+ // forge-lint: disable-next-line(unaliased-plain-import)
11
17
  import "@bananapus/core-v6/script/helpers/CoreDeploymentLib.sol";
18
+ // forge-lint: disable-next-line(unaliased-plain-import)
12
19
  import "@bananapus/721-hook-v6/script/helpers/Hook721DeploymentLib.sol";
20
+ // forge-lint: disable-next-line(unaliased-plain-import)
13
21
  import "@bananapus/suckers-v6/script/helpers/SuckerDeploymentLib.sol";
22
+ // forge-lint: disable-next-line(unaliased-plain-import)
14
23
  import "@croptop/core-v6/script/helpers/CroptopDeploymentLib.sol";
24
+ // forge-lint: disable-next-line(unaliased-plain-import)
15
25
  import "@bananapus/router-terminal-v6/script/helpers/RouterTerminalDeploymentLib.sol";
16
26
 
17
27
  import {JBConstants} from "@bananapus/core-v6/src/libraries/JBConstants.sol";
@@ -21,6 +31,8 @@ import {REVStageConfig, REVAutoIssuance} from "../src/structs/REVStageConfig.sol
21
31
  import {REVLoanSource} from "../src/structs/REVLoanSource.sol";
22
32
  import {REVDescription} from "../src/structs/REVDescription.sol";
23
33
  import {IREVLoans} from "./../src/interfaces/IREVLoans.sol";
34
+ import {JBPermissioned} from "@bananapus/core-v6/src/abstract/JBPermissioned.sol";
35
+ import {JBPermissionIds} from "@bananapus/permission-ids-v6/src/JBPermissionIds.sol";
24
36
  import {JBSuckerDeployerConfig} from "@bananapus/suckers-v6/src/structs/JBSuckerDeployerConfig.sol";
25
37
  import {JBSuckerRegistry} from "@bananapus/suckers-v6/src/JBSuckerRegistry.sol";
26
38
  import {JB721TiersHookDeployer} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
@@ -37,28 +49,42 @@ struct FeeProjectConfig {
37
49
 
38
50
  contract REVLoansUnsourcedTests is TestBaseWorkflow {
39
51
  /// @notice the salts that are used to deploy the contracts.
52
+ // forge-lint: disable-next-line(mixed-case-variable)
40
53
  bytes32 REV_DEPLOYER_SALT = "REVDeployer";
54
+ // forge-lint: disable-next-line(mixed-case-variable)
41
55
  bytes32 ERC20_SALT = "REV_TOKEN";
42
56
 
57
+ // forge-lint: disable-next-line(mixed-case-variable)
43
58
  REVDeployer REV_DEPLOYER;
59
+ // forge-lint: disable-next-line(mixed-case-variable)
44
60
  JB721TiersHook EXAMPLE_HOOK;
45
61
 
46
62
  /// @notice Deploys tiered ERC-721 hooks for revnets.
63
+ // forge-lint: disable-next-line(mixed-case-variable)
47
64
  IJB721TiersHookDeployer HOOK_DEPLOYER;
65
+ // forge-lint: disable-next-line(mixed-case-variable)
48
66
  IJB721TiersHookStore HOOK_STORE;
67
+ // forge-lint: disable-next-line(mixed-case-variable)
49
68
  IJBAddressRegistry ADDRESS_REGISTRY;
50
69
 
70
+ // forge-lint: disable-next-line(mixed-case-variable)
51
71
  IREVLoans LOANS_CONTRACT;
52
72
 
53
73
  /// @notice Deploys and tracks suckers for revnets.
74
+ // forge-lint: disable-next-line(mixed-case-variable)
54
75
  IJBSuckerRegistry SUCKER_REGISTRY;
55
76
 
77
+ // forge-lint: disable-next-line(mixed-case-variable)
56
78
  CTPublisher PUBLISHER;
79
+ // forge-lint: disable-next-line(mixed-case-variable)
57
80
  MockBuybackDataHook MOCK_BUYBACK;
58
81
 
82
+ // forge-lint: disable-next-line(mixed-case-variable)
59
83
  uint256 FEE_PROJECT_ID;
84
+ // forge-lint: disable-next-line(mixed-case-variable)
60
85
  uint256 REVNET_ID;
61
86
 
87
+ // forge-lint: disable-next-line(mixed-case-variable)
62
88
  address USER = makeAddr("user");
63
89
 
64
90
  /// @notice The address that is allowed to forward calls.
@@ -95,7 +121,11 @@ contract REVLoansUnsourcedTests is TestBaseWorkflow {
95
121
  {
96
122
  REVAutoIssuance[] memory issuanceConfs = new REVAutoIssuance[](1);
97
123
  issuanceConfs[0] = REVAutoIssuance({
98
- chainId: uint32(block.chainid), count: uint104(70_000 * decimalMultiplier), beneficiary: multisig()
124
+ // forge-lint: disable-next-line(unsafe-typecast)
125
+ chainId: uint32(block.chainid),
126
+ // forge-lint: disable-next-line(unsafe-typecast)
127
+ count: uint104(70_000 * decimalMultiplier),
128
+ beneficiary: multisig()
99
129
  });
100
130
 
101
131
  stageConfigurations[0] = REVStageConfig({
@@ -103,6 +133,7 @@ contract REVLoansUnsourcedTests is TestBaseWorkflow {
103
133
  autoIssuances: issuanceConfs,
104
134
  splitPercent: 2000, // 20%
105
135
  splits: splits,
136
+ // forge-lint: disable-next-line(unsafe-typecast)
106
137
  initialIssuance: uint112(1000 * decimalMultiplier),
107
138
  issuanceCutFrequency: 90 days,
108
139
  issuanceCutPercent: JBConstants.MAX_WEIGHT_CUT_PERCENT / 2,
@@ -137,6 +168,7 @@ contract REVLoansUnsourcedTests is TestBaseWorkflow {
137
168
 
138
169
  // The project's revnet configuration
139
170
  REVConfig memory revnetConfiguration = REVConfig({
171
+ // forge-lint: disable-next-line(named-struct-fields)
140
172
  description: REVDescription(name, symbol, projectUri, ERC20_SALT),
141
173
  baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
142
174
  splitOperator: multisig(),
@@ -183,7 +215,11 @@ contract REVLoansUnsourcedTests is TestBaseWorkflow {
183
215
  {
184
216
  REVAutoIssuance[] memory issuanceConfs = new REVAutoIssuance[](1);
185
217
  issuanceConfs[0] = REVAutoIssuance({
186
- chainId: uint32(block.chainid), count: uint104(70_000 * decimalMultiplier), beneficiary: multisig()
218
+ // forge-lint: disable-next-line(unsafe-typecast)
219
+ chainId: uint32(block.chainid),
220
+ // forge-lint: disable-next-line(unsafe-typecast)
221
+ count: uint104(70_000 * decimalMultiplier),
222
+ beneficiary: multisig()
187
223
  });
188
224
 
189
225
  stageConfigurations[0] = REVStageConfig({
@@ -191,6 +227,7 @@ contract REVLoansUnsourcedTests is TestBaseWorkflow {
191
227
  autoIssuances: issuanceConfs,
192
228
  splitPercent: 2000, // 20%
193
229
  splits: splits,
230
+ // forge-lint: disable-next-line(unsafe-typecast)
194
231
  initialIssuance: uint112(1000 * decimalMultiplier),
195
232
  issuanceCutFrequency: 90 days,
196
233
  issuanceCutPercent: JBConstants.MAX_WEIGHT_CUT_PERCENT / 2,
@@ -225,6 +262,7 @@ contract REVLoansUnsourcedTests is TestBaseWorkflow {
225
262
 
226
263
  // The project's revnet configuration
227
264
  REVConfig memory revnetConfiguration = REVConfig({
265
+ // forge-lint: disable-next-line(named-struct-fields)
228
266
  description: REVDescription(name, symbol, projectUri, "NANA_TOKEN"),
229
267
  baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
230
268
  splitOperator: multisig(),
@@ -249,8 +287,9 @@ contract REVLoansUnsourcedTests is TestBaseWorkflow {
249
287
 
250
288
  HOOK_STORE = new JB721TiersHookStore();
251
289
 
252
- EXAMPLE_HOOK =
253
- new JB721TiersHook(jbDirectory(), jbPermissions(), jbRulesets(), HOOK_STORE, jbSplits(), multisig());
290
+ EXAMPLE_HOOK = new JB721TiersHook(
291
+ jbDirectory(), jbPermissions(), jbPrices(), jbRulesets(), HOOK_STORE, jbSplits(), multisig()
292
+ );
254
293
 
255
294
  ADDRESS_REGISTRY = new JBAddressRegistry();
256
295
 
@@ -288,22 +327,26 @@ contract REVLoansUnsourcedTests is TestBaseWorkflow {
288
327
 
289
328
  vm.prank(address(multisig()));
290
329
  // Configure the project.
291
- REVNET_ID = REV_DEPLOYER.deployFor({
330
+ (REVNET_ID,) = REV_DEPLOYER.deployFor({
292
331
  revnetId: FEE_PROJECT_ID, // Zero to deploy a new revnet
293
332
  configuration: feeProjectConfig.configuration,
294
333
  terminalConfigurations: feeProjectConfig.terminalConfigurations,
295
- suckerDeploymentConfiguration: feeProjectConfig.suckerDeploymentConfiguration
334
+ suckerDeploymentConfiguration: feeProjectConfig.suckerDeploymentConfiguration,
335
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
336
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
296
337
  });
297
338
 
298
339
  // Configure second revnet
299
340
  FeeProjectConfig memory fee2Config = getSecondProjectConfig();
300
341
 
301
342
  // Configure the project.
302
- REVNET_ID = REV_DEPLOYER.deployFor({
343
+ (REVNET_ID,) = REV_DEPLOYER.deployFor({
303
344
  revnetId: 0, // Zero to deploy a new revnet
304
345
  configuration: fee2Config.configuration,
305
346
  terminalConfigurations: fee2Config.terminalConfigurations,
306
- suckerDeploymentConfiguration: fee2Config.suckerDeploymentConfiguration
347
+ suckerDeploymentConfiguration: fee2Config.suckerDeploymentConfiguration,
348
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
349
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
307
350
  });
308
351
 
309
352
  // Give Eth for the user experience
@@ -322,7 +365,15 @@ contract REVLoansUnsourcedTests is TestBaseWorkflow {
322
365
 
323
366
  // Loan fund access limits are now auto-derived from terminal configs, so the surplus allowance exists.
324
367
  // The borrow still fails because USER hasn't approved LOANS to burn their tokens as collateral.
325
- vm.expectRevert();
368
+ vm.expectRevert(
369
+ abi.encodeWithSelector(
370
+ JBPermissioned.JBPermissioned_Unauthorized.selector,
371
+ USER, // account (the token holder)
372
+ address(LOANS_CONTRACT), // sender (the contract trying to burn)
373
+ REVNET_ID, // projectId
374
+ JBPermissionIds.BURN_TOKENS // permissionId
375
+ )
376
+ );
326
377
 
327
378
  REVLoanSource memory sauce = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: jbMultiTerminal()});
328
379
 
@@ -1,26 +1,33 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  pragma solidity 0.8.26;
3
3
 
4
+ // forge-lint: disable-next-line(unaliased-plain-import)
4
5
  import "forge-std/Test.sol";
6
+ // forge-lint: disable-next-line(unaliased-plain-import)
5
7
  import /* {*} from */ "@bananapus/core-v6/test/helpers/TestBaseWorkflow.sol";
6
- import /* {*} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
8
+ // import /* {*} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
9
+ // forge-lint: disable-next-line(unaliased-plain-import)
7
10
  import /* {*} from */ "./../src/REVDeployer.sol";
11
+ // forge-lint: disable-next-line(unaliased-plain-import)
8
12
  import "@croptop/core-v6/src/CTPublisher.sol";
9
13
  import {MockBuybackDataHook} from "./mock/MockBuybackDataHook.sol";
14
+ import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
10
15
 
16
+ // forge-lint: disable-next-line(unaliased-plain-import)
11
17
  import "@bananapus/core-v6/script/helpers/CoreDeploymentLib.sol";
18
+ // forge-lint: disable-next-line(unaliased-plain-import)
12
19
  import "@bananapus/721-hook-v6/script/helpers/Hook721DeploymentLib.sol";
20
+ // forge-lint: disable-next-line(unaliased-plain-import)
13
21
  import "@bananapus/suckers-v6/script/helpers/SuckerDeploymentLib.sol";
22
+ // forge-lint: disable-next-line(unaliased-plain-import)
14
23
  import "@croptop/core-v6/script/helpers/CroptopDeploymentLib.sol";
24
+ // forge-lint: disable-next-line(unaliased-plain-import)
15
25
  import "@bananapus/router-terminal-v6/script/helpers/RouterTerminalDeploymentLib.sol";
16
26
  import {JBConstants} from "@bananapus/core-v6/src/libraries/JBConstants.sol";
17
27
  import {JBAccountingContext} from "@bananapus/core-v6/src/structs/JBAccountingContext.sol";
18
- import {MockPriceFeed} from "@bananapus/core-v6/test/mock/MockPriceFeed.sol";
19
28
  import {MockERC20} from "@bananapus/core-v6/test/mock/MockERC20.sol";
20
29
  import {REVLoans} from "../src/REVLoans.sol";
21
- import {REVLoan} from "../src/structs/REVLoan.sol";
22
30
  import {REVStageConfig, REVAutoIssuance} from "../src/structs/REVStageConfig.sol";
23
- import {REVLoanSource} from "../src/structs/REVLoanSource.sol";
24
31
  import {REVDescription} from "../src/structs/REVDescription.sol";
25
32
  import {IREVLoans} from "./../src/interfaces/IREVLoans.sol";
26
33
  import {JBSuckerDeployerConfig} from "@bananapus/suckers-v6/src/structs/JBSuckerDeployerConfig.sol";
@@ -38,24 +45,40 @@ struct FeeProjectConfig {
38
45
  }
39
46
 
40
47
  contract TestBurnHeldTokens is TestBaseWorkflow {
48
+ // forge-lint: disable-next-line(mixed-case-variable)
41
49
  bytes32 REV_DEPLOYER_SALT = "REVDeployer";
50
+ // forge-lint: disable-next-line(mixed-case-variable)
42
51
  bytes32 ERC20_SALT = "REV_TOKEN";
43
52
 
53
+ // forge-lint: disable-next-line(mixed-case-variable)
44
54
  REVDeployer REV_DEPLOYER;
55
+ // forge-lint: disable-next-line(mixed-case-variable)
45
56
  JB721TiersHook EXAMPLE_HOOK;
57
+ // forge-lint: disable-next-line(mixed-case-variable)
46
58
  IJB721TiersHookDeployer HOOK_DEPLOYER;
59
+ // forge-lint: disable-next-line(mixed-case-variable)
47
60
  IJB721TiersHookStore HOOK_STORE;
61
+ // forge-lint: disable-next-line(mixed-case-variable)
48
62
  IJBAddressRegistry ADDRESS_REGISTRY;
63
+ // forge-lint: disable-next-line(mixed-case-variable)
49
64
  IREVLoans LOANS_CONTRACT;
65
+ // forge-lint: disable-next-line(mixed-case-variable)
50
66
  MockERC20 TOKEN;
67
+ // forge-lint: disable-next-line(mixed-case-variable)
51
68
  IJBSuckerRegistry SUCKER_REGISTRY;
69
+ // forge-lint: disable-next-line(mixed-case-variable)
52
70
  CTPublisher PUBLISHER;
71
+ // forge-lint: disable-next-line(mixed-case-variable)
53
72
  MockBuybackDataHook MOCK_BUYBACK;
54
73
 
74
+ // forge-lint: disable-next-line(mixed-case-variable)
55
75
  uint256 FEE_PROJECT_ID;
76
+ // forge-lint: disable-next-line(mixed-case-variable)
56
77
  uint256 REVNET_ID;
57
78
 
79
+ // forge-lint: disable-next-line(mixed-case-variable)
58
80
  address USER = makeAddr("user");
81
+ // forge-lint: disable-next-line(mixed-case-variable)
59
82
  address RANDOM_CALLER = makeAddr("randomCaller");
60
83
 
61
84
  address private constant TRUSTED_FORWARDER = 0xB2b5841DBeF766d4b521221732F9B618fCf34A87;
@@ -83,6 +106,7 @@ contract TestBurnHeldTokens is TestBaseWorkflow {
83
106
  autoIssuances: new REVAutoIssuance[](0),
84
107
  splitPercent: 2000,
85
108
  splits: splits,
109
+ // forge-lint: disable-next-line(unsafe-typecast)
86
110
  initialIssuance: uint112(1000 * decimalMultiplier),
87
111
  issuanceCutFrequency: 90 days,
88
112
  issuanceCutPercent: JBConstants.MAX_WEIGHT_CUT_PERCENT / 2,
@@ -91,6 +115,7 @@ contract TestBurnHeldTokens is TestBaseWorkflow {
91
115
  });
92
116
 
93
117
  REVConfig memory revnetConfiguration = REVConfig({
118
+ // forge-lint: disable-next-line(named-struct-fields)
94
119
  description: REVDescription("Revnet", "$REV", "ipfs://test", ERC20_SALT),
95
120
  baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
96
121
  splitOperator: multisig(),
@@ -133,6 +158,7 @@ contract TestBurnHeldTokens is TestBaseWorkflow {
133
158
  autoIssuances: new REVAutoIssuance[](0),
134
159
  splitPercent: 2000, // 20% reserved
135
160
  splits: splits,
161
+ // forge-lint: disable-next-line(unsafe-typecast)
136
162
  initialIssuance: uint112(1000 * decimalMultiplier),
137
163
  issuanceCutFrequency: 0,
138
164
  issuanceCutPercent: 0,
@@ -141,19 +167,22 @@ contract TestBurnHeldTokens is TestBaseWorkflow {
141
167
  });
142
168
 
143
169
  REVConfig memory revnetConfiguration = REVConfig({
170
+ // forge-lint: disable-next-line(named-struct-fields)
144
171
  description: REVDescription("Partial", "$PRT", "ipfs://test", "PRT_TOKEN"),
145
172
  baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
146
173
  splitOperator: multisig(),
147
174
  stageConfigurations: stageConfigurations
148
175
  });
149
176
 
150
- revnetId = REV_DEPLOYER.deployFor({
177
+ (revnetId,) = REV_DEPLOYER.deployFor({
151
178
  revnetId: 0,
152
179
  configuration: revnetConfiguration,
153
180
  terminalConfigurations: terminalConfigurations,
154
181
  suckerDeploymentConfiguration: REVSuckerDeploymentConfig({
155
182
  deployerConfigurations: new JBSuckerDeployerConfig[](0), salt: keccak256(abi.encodePacked("PRT"))
156
- })
183
+ }),
184
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
185
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
157
186
  });
158
187
  }
159
188
 
@@ -163,8 +192,9 @@ contract TestBurnHeldTokens is TestBaseWorkflow {
163
192
  FEE_PROJECT_ID = jbProjects().createFor(multisig());
164
193
  SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
165
194
  HOOK_STORE = new JB721TiersHookStore();
166
- EXAMPLE_HOOK =
167
- new JB721TiersHook(jbDirectory(), jbPermissions(), jbRulesets(), HOOK_STORE, jbSplits(), multisig());
195
+ EXAMPLE_HOOK = new JB721TiersHook(
196
+ jbDirectory(), jbPermissions(), jbPrices(), jbRulesets(), HOOK_STORE, jbSplits(), multisig()
197
+ );
168
198
  ADDRESS_REGISTRY = new JBAddressRegistry();
169
199
  HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
170
200
  PUBLISHER = new CTPublisher(jbDirectory(), jbPermissions(), FEE_PROJECT_ID, multisig());
@@ -201,7 +231,9 @@ contract TestBurnHeldTokens is TestBaseWorkflow {
201
231
  revnetId: FEE_PROJECT_ID,
202
232
  configuration: feeProjectConfig.configuration,
203
233
  terminalConfigurations: feeProjectConfig.terminalConfigurations,
204
- suckerDeploymentConfiguration: feeProjectConfig.suckerDeploymentConfiguration
234
+ suckerDeploymentConfiguration: feeProjectConfig.suckerDeploymentConfiguration,
235
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
236
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
205
237
  });
206
238
 
207
239
  // Deploy revnet with partial splits.
@@ -283,6 +315,7 @@ contract TestBurnHeldTokens is TestBaseWorkflow {
283
315
  autoIssuances: new REVAutoIssuance[](0),
284
316
  splitPercent: 2000,
285
317
  splits: splits,
318
+ // forge-lint: disable-next-line(unsafe-typecast)
286
319
  initialIssuance: uint112(1000 * decimalMultiplier),
287
320
  issuanceCutFrequency: 0,
288
321
  issuanceCutPercent: 0,
@@ -290,9 +323,10 @@ contract TestBurnHeldTokens is TestBaseWorkflow {
290
323
  extraMetadata: 0
291
324
  });
292
325
 
293
- uint256 fullSplitRevnetId = REV_DEPLOYER.deployFor({
326
+ (uint256 fullSplitRevnetId,) = REV_DEPLOYER.deployFor({
294
327
  revnetId: 0,
295
328
  configuration: REVConfig({
329
+ // forge-lint: disable-next-line(named-struct-fields)
296
330
  description: REVDescription("Full", "$FUL", "ipfs://test", "FUL_TOKEN"),
297
331
  baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
298
332
  splitOperator: multisig(),
@@ -301,7 +335,9 @@ contract TestBurnHeldTokens is TestBaseWorkflow {
301
335
  terminalConfigurations: terminalConfigurations,
302
336
  suckerDeploymentConfiguration: REVSuckerDeploymentConfig({
303
337
  deployerConfigurations: new JBSuckerDeployerConfig[](0), salt: keccak256(abi.encodePacked("FUL"))
304
- })
338
+ }),
339
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
340
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
305
341
  });
306
342
 
307
343
  // REVDeployer should have no tokens for this revnet.