@rev-net/core-v6 0.0.12 → 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 (78) hide show
  1. package/AUDIT_INSTRUCTIONS.md +295 -0
  2. package/CHANGE_LOG.md +316 -0
  3. package/README.md +2 -2
  4. package/RISKS.md +180 -35
  5. package/SKILLS.md +1 -1
  6. package/USER_JOURNEYS.md +489 -0
  7. package/package.json +9 -9
  8. package/script/Deploy.s.sol +40 -6
  9. package/script/helpers/RevnetCoreDeploymentLib.sol +7 -1
  10. package/src/REVDeployer.sol +63 -47
  11. package/src/REVLoans.sol +51 -15
  12. package/src/interfaces/IREVDeployer.sol +0 -1
  13. package/src/structs/REV721TiersHookFlags.sol +1 -0
  14. package/src/structs/REVAutoIssuance.sol +1 -0
  15. package/src/structs/REVBaseline721HookConfig.sol +1 -0
  16. package/src/structs/REVConfig.sol +1 -0
  17. package/src/structs/REVCroptopAllowedPost.sol +1 -0
  18. package/src/structs/REVDeploy721TiersHookConfig.sol +1 -0
  19. package/src/structs/REVDescription.sol +1 -0
  20. package/src/structs/REVLoan.sol +1 -0
  21. package/src/structs/REVLoanSource.sol +1 -0
  22. package/src/structs/REVStageConfig.sol +1 -0
  23. package/src/structs/REVSuckerDeploymentConfig.sol +1 -0
  24. package/test/REV.integrations.t.sol +132 -12
  25. package/test/REVAutoIssuanceFuzz.t.sol +23 -3
  26. package/test/REVDeployerRegressions.t.sol +35 -4
  27. package/test/REVInvincibility.t.sol +58 -8
  28. package/test/REVInvincibilityHandler.sol +29 -0
  29. package/test/REVLifecycle.t.sol +28 -3
  30. package/test/REVLoans.invariants.t.sol +52 -5
  31. package/test/REVLoansAttacks.t.sol +43 -5
  32. package/test/REVLoansFeeRecovery.t.sol +50 -11
  33. package/test/REVLoansFindings.t.sol +27 -3
  34. package/test/REVLoansRegressions.t.sol +25 -3
  35. package/test/REVLoansSourceFeeRecovery.t.sol +491 -0
  36. package/test/REVLoansSourced.t.sol +56 -7
  37. package/test/REVLoansUnSourced.t.sol +49 -5
  38. package/test/TestBurnHeldTokens.t.sol +32 -5
  39. package/test/TestCEIPattern.t.sol +26 -2
  40. package/test/TestCashOutCallerValidation.t.sol +30 -4
  41. package/test/TestConversionDocumentation.t.sol +26 -5
  42. package/test/TestCrossCurrencyReclaim.t.sol +584 -0
  43. package/test/TestCrossSourceReallocation.t.sol +26 -2
  44. package/test/TestERC2771MetaTx.t.sol +557 -0
  45. package/test/TestEmptyBuybackSpecs.t.sol +23 -3
  46. package/test/TestFlashLoanSurplus.t.sol +28 -3
  47. package/test/TestHookArrayOOB.t.sol +24 -4
  48. package/test/TestLiquidationBehavior.t.sol +26 -3
  49. package/test/TestLoanSourceRotation.t.sol +525 -0
  50. package/test/TestLongTailEconomics.t.sol +651 -0
  51. package/test/TestLowFindings.t.sol +65 -2
  52. package/test/TestMixedFixes.t.sol +28 -3
  53. package/test/TestPermit2Signatures.t.sol +657 -0
  54. package/test/TestReallocationSandwich.t.sol +384 -0
  55. package/test/TestRevnetRegressions.t.sol +324 -0
  56. package/test/TestSplitWeightAdjustment.t.sol +24 -2
  57. package/test/TestSplitWeightE2E.t.sol +29 -2
  58. package/test/TestSplitWeightFork.t.sol +46 -7
  59. package/test/TestStageTransitionBorrowable.t.sol +24 -2
  60. package/test/TestSwapTerminalPermission.t.sol +23 -3
  61. package/test/TestUint112Overflow.t.sol +28 -2
  62. package/test/TestZeroRepayment.t.sol +26 -2
  63. package/test/fork/ForkTestBase.sol +46 -3
  64. package/test/fork/TestCashOutFork.t.sol +1 -1
  65. package/test/fork/TestLoanBorrowFork.t.sol +1 -0
  66. package/test/fork/TestLoanCrossRulesetFork.t.sol +3 -1
  67. package/test/fork/TestLoanLiquidationFork.t.sol +1 -0
  68. package/test/fork/TestLoanReallocateFork.t.sol +1 -0
  69. package/test/fork/TestLoanRepayFork.t.sol +1 -0
  70. package/test/fork/TestLoanTransferFork.t.sol +133 -0
  71. package/test/fork/TestSplitWeightFork.t.sol +3 -0
  72. package/test/helpers/REVEmpty721Config.sol +1 -0
  73. package/test/mock/MockBuybackDataHook.sol +1 -0
  74. package/test/regression/TestBurnPermissionRequired.t.sol +267 -0
  75. package/test/regression/TestCrossRevnetLiquidation.t.sol +228 -0
  76. package/test/regression/TestCumulativeLoanCounter.t.sol +27 -4
  77. package/test/regression/TestLiquidateGapHandling.t.sol +29 -4
  78. 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";
@@ -32,7 +41,6 @@ import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStor
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";
34
43
  import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
35
- import {REVCroptopAllowedPost} from "../src/structs/REVCroptopAllowedPost.sol";
36
44
 
37
45
  struct FeeProjectConfig {
38
46
  REVConfig configuration;
@@ -42,30 +50,45 @@ struct FeeProjectConfig {
42
50
 
43
51
  contract REVLoansSourcedTests is TestBaseWorkflow {
44
52
  /// @notice the salts that are used to deploy the contracts.
53
+ // forge-lint: disable-next-line(mixed-case-variable)
45
54
  bytes32 REV_DEPLOYER_SALT = "REVDeployer";
55
+ // forge-lint: disable-next-line(mixed-case-variable)
46
56
  bytes32 ERC20_SALT = "REV_TOKEN";
47
57
 
58
+ // forge-lint: disable-next-line(mixed-case-variable)
48
59
  REVDeployer REV_DEPLOYER;
60
+ // forge-lint: disable-next-line(mixed-case-variable)
49
61
  JB721TiersHook EXAMPLE_HOOK;
50
62
 
51
63
  /// @notice Deploys tiered ERC-721 hooks for revnets.
64
+ // forge-lint: disable-next-line(mixed-case-variable)
52
65
  IJB721TiersHookDeployer HOOK_DEPLOYER;
66
+ // forge-lint: disable-next-line(mixed-case-variable)
53
67
  IJB721TiersHookStore HOOK_STORE;
68
+ // forge-lint: disable-next-line(mixed-case-variable)
54
69
  IJBAddressRegistry ADDRESS_REGISTRY;
55
70
 
71
+ // forge-lint: disable-next-line(mixed-case-variable)
56
72
  IREVLoans LOANS_CONTRACT;
57
73
 
74
+ // forge-lint: disable-next-line(mixed-case-variable)
58
75
  MockERC20 TOKEN;
59
76
 
60
77
  /// @notice Deploys and tracks suckers for revnets.
78
+ // forge-lint: disable-next-line(mixed-case-variable)
61
79
  IJBSuckerRegistry SUCKER_REGISTRY;
62
80
 
81
+ // forge-lint: disable-next-line(mixed-case-variable)
63
82
  CTPublisher PUBLISHER;
83
+ // forge-lint: disable-next-line(mixed-case-variable)
64
84
  MockBuybackDataHook MOCK_BUYBACK;
65
85
 
86
+ // forge-lint: disable-next-line(mixed-case-variable)
66
87
  uint256 FEE_PROJECT_ID;
88
+ // forge-lint: disable-next-line(mixed-case-variable)
67
89
  uint256 REVNET_ID;
68
90
 
91
+ // forge-lint: disable-next-line(mixed-case-variable)
69
92
  address USER = makeAddr("user");
70
93
 
71
94
  /// @notice The address that is allowed to forward calls.
@@ -107,7 +130,11 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
107
130
  {
108
131
  REVAutoIssuance[] memory issuanceConfs = new REVAutoIssuance[](1);
109
132
  issuanceConfs[0] = REVAutoIssuance({
110
- 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()
111
138
  });
112
139
 
113
140
  stageConfigurations[0] = REVStageConfig({
@@ -115,6 +142,7 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
115
142
  autoIssuances: issuanceConfs,
116
143
  splitPercent: 2000, // 20%
117
144
  splits: splits,
145
+ // forge-lint: disable-next-line(unsafe-typecast)
118
146
  initialIssuance: uint112(1000 * decimalMultiplier),
119
147
  issuanceCutFrequency: 90 days,
120
148
  issuanceCutPercent: JBConstants.MAX_WEIGHT_CUT_PERCENT / 2,
@@ -149,6 +177,7 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
149
177
 
150
178
  // The project's revnet configuration
151
179
  REVConfig memory revnetConfiguration = REVConfig({
180
+ // forge-lint: disable-next-line(named-struct-fields)
152
181
  description: REVDescription(name, symbol, projectUri, ERC20_SALT),
153
182
  baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
154
183
  splitOperator: multisig(),
@@ -198,7 +227,11 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
198
227
  {
199
228
  REVAutoIssuance[] memory issuanceConfs = new REVAutoIssuance[](1);
200
229
  issuanceConfs[0] = REVAutoIssuance({
201
- 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()
202
235
  });
203
236
 
204
237
  stageConfigurations[0] = REVStageConfig({
@@ -206,6 +239,7 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
206
239
  autoIssuances: issuanceConfs,
207
240
  splitPercent: 2000, // 20%
208
241
  splits: splits,
242
+ // forge-lint: disable-next-line(unsafe-typecast)
209
243
  initialIssuance: uint112(1000 * decimalMultiplier),
210
244
  issuanceCutFrequency: 90 days,
211
245
  issuanceCutPercent: JBConstants.MAX_WEIGHT_CUT_PERCENT / 2,
@@ -240,6 +274,7 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
240
274
 
241
275
  // The project's revnet configuration
242
276
  REVConfig memory revnetConfiguration = REVConfig({
277
+ // forge-lint: disable-next-line(named-struct-fields)
243
278
  description: REVDescription(name, symbol, projectUri, "NANA_TOKEN"),
244
279
  baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
245
280
  splitOperator: multisig(),
@@ -517,6 +552,7 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
517
552
  uint256 amountPaid = balanceBefore - TOKEN.balanceOf(USER);
518
553
 
519
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)
520
556
  uint256 expectedFee = (loan.amount * (1000 - prepaidFee) / 1000) * expectedFeePercent / 1000;
521
557
 
522
558
  // The fee may deviate 1%.
@@ -574,11 +610,14 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
574
610
  assertEq(TOKEN.balanceOf(address(LOANS_CONTRACT)), 0);
575
611
 
576
612
  // The fees to be paid to NANA.
613
+ // forge-lint: disable-next-line(mixed-case-variable)
577
614
  uint256 allowance_fees = JBFees.feeAmountFrom({amountBeforeFee: loanable, feePercent: jbMultiTerminal().FEE()});
578
615
  // The fees to be paid to REV.
616
+ // forge-lint: disable-next-line(mixed-case-variable)
579
617
  uint256 rev_fees =
580
618
  JBFees.feeAmountFrom({amountBeforeFee: loanable, feePercent: LOANS_CONTRACT.REV_PREPAID_FEE_PERCENT()});
581
619
  // The fees to be paid to the Project we are taking a loan from.
620
+ // forge-lint: disable-next-line(mixed-case-variable)
582
621
  uint256 source_fees = JBFees.feeAmountFrom({amountBeforeFee: loanable, feePercent: prepaidFee});
583
622
  uint256 fees = allowance_fees + rev_fees + source_fees;
584
623
 
@@ -670,7 +709,12 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
670
709
 
671
710
  // Check what a borrow would result in more.
672
711
  uint256 loanable = LOANS_CONTRACT.borrowableAmountFrom(
673
- 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))
674
718
  );
675
719
 
676
720
  uint256 fullReclaimableSurplus = jbMultiTerminal().STORE()
@@ -1126,7 +1170,8 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
1126
1170
  if (premint > 0) {
1127
1171
  issuanceConfs = new REVAutoIssuance[](1);
1128
1172
  issuanceConfs[0] =
1129
- 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()});
1130
1175
  }
1131
1176
 
1132
1177
  JBSplit[] memory splits = new JBSplit[](1);
@@ -1176,7 +1221,11 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
1176
1221
  permissionIds[0] = JBPermissionIds.BURN_TOKENS;
1177
1222
 
1178
1223
  JBPermissionsData memory permissionsData = JBPermissionsData({
1179
- 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
1180
1229
  });
1181
1230
 
1182
1231
  // Give the loans contract permission to our tokens.
@@ -1,19 +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";
10
14
  import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
11
- import {REVCroptopAllowedPost} from "../src/structs/REVCroptopAllowedPost.sol";
12
15
 
16
+ // forge-lint: disable-next-line(unaliased-plain-import)
13
17
  import "@bananapus/core-v6/script/helpers/CoreDeploymentLib.sol";
18
+ // forge-lint: disable-next-line(unaliased-plain-import)
14
19
  import "@bananapus/721-hook-v6/script/helpers/Hook721DeploymentLib.sol";
20
+ // forge-lint: disable-next-line(unaliased-plain-import)
15
21
  import "@bananapus/suckers-v6/script/helpers/SuckerDeploymentLib.sol";
22
+ // forge-lint: disable-next-line(unaliased-plain-import)
16
23
  import "@croptop/core-v6/script/helpers/CroptopDeploymentLib.sol";
24
+ // forge-lint: disable-next-line(unaliased-plain-import)
17
25
  import "@bananapus/router-terminal-v6/script/helpers/RouterTerminalDeploymentLib.sol";
18
26
 
19
27
  import {JBConstants} from "@bananapus/core-v6/src/libraries/JBConstants.sol";
@@ -23,6 +31,8 @@ import {REVStageConfig, REVAutoIssuance} from "../src/structs/REVStageConfig.sol
23
31
  import {REVLoanSource} from "../src/structs/REVLoanSource.sol";
24
32
  import {REVDescription} from "../src/structs/REVDescription.sol";
25
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";
26
36
  import {JBSuckerDeployerConfig} from "@bananapus/suckers-v6/src/structs/JBSuckerDeployerConfig.sol";
27
37
  import {JBSuckerRegistry} from "@bananapus/suckers-v6/src/JBSuckerRegistry.sol";
28
38
  import {JB721TiersHookDeployer} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
@@ -39,28 +49,42 @@ struct FeeProjectConfig {
39
49
 
40
50
  contract REVLoansUnsourcedTests is TestBaseWorkflow {
41
51
  /// @notice the salts that are used to deploy the contracts.
52
+ // forge-lint: disable-next-line(mixed-case-variable)
42
53
  bytes32 REV_DEPLOYER_SALT = "REVDeployer";
54
+ // forge-lint: disable-next-line(mixed-case-variable)
43
55
  bytes32 ERC20_SALT = "REV_TOKEN";
44
56
 
57
+ // forge-lint: disable-next-line(mixed-case-variable)
45
58
  REVDeployer REV_DEPLOYER;
59
+ // forge-lint: disable-next-line(mixed-case-variable)
46
60
  JB721TiersHook EXAMPLE_HOOK;
47
61
 
48
62
  /// @notice Deploys tiered ERC-721 hooks for revnets.
63
+ // forge-lint: disable-next-line(mixed-case-variable)
49
64
  IJB721TiersHookDeployer HOOK_DEPLOYER;
65
+ // forge-lint: disable-next-line(mixed-case-variable)
50
66
  IJB721TiersHookStore HOOK_STORE;
67
+ // forge-lint: disable-next-line(mixed-case-variable)
51
68
  IJBAddressRegistry ADDRESS_REGISTRY;
52
69
 
70
+ // forge-lint: disable-next-line(mixed-case-variable)
53
71
  IREVLoans LOANS_CONTRACT;
54
72
 
55
73
  /// @notice Deploys and tracks suckers for revnets.
74
+ // forge-lint: disable-next-line(mixed-case-variable)
56
75
  IJBSuckerRegistry SUCKER_REGISTRY;
57
76
 
77
+ // forge-lint: disable-next-line(mixed-case-variable)
58
78
  CTPublisher PUBLISHER;
79
+ // forge-lint: disable-next-line(mixed-case-variable)
59
80
  MockBuybackDataHook MOCK_BUYBACK;
60
81
 
82
+ // forge-lint: disable-next-line(mixed-case-variable)
61
83
  uint256 FEE_PROJECT_ID;
84
+ // forge-lint: disable-next-line(mixed-case-variable)
62
85
  uint256 REVNET_ID;
63
86
 
87
+ // forge-lint: disable-next-line(mixed-case-variable)
64
88
  address USER = makeAddr("user");
65
89
 
66
90
  /// @notice The address that is allowed to forward calls.
@@ -97,7 +121,11 @@ contract REVLoansUnsourcedTests is TestBaseWorkflow {
97
121
  {
98
122
  REVAutoIssuance[] memory issuanceConfs = new REVAutoIssuance[](1);
99
123
  issuanceConfs[0] = REVAutoIssuance({
100
- 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()
101
129
  });
102
130
 
103
131
  stageConfigurations[0] = REVStageConfig({
@@ -105,6 +133,7 @@ contract REVLoansUnsourcedTests is TestBaseWorkflow {
105
133
  autoIssuances: issuanceConfs,
106
134
  splitPercent: 2000, // 20%
107
135
  splits: splits,
136
+ // forge-lint: disable-next-line(unsafe-typecast)
108
137
  initialIssuance: uint112(1000 * decimalMultiplier),
109
138
  issuanceCutFrequency: 90 days,
110
139
  issuanceCutPercent: JBConstants.MAX_WEIGHT_CUT_PERCENT / 2,
@@ -139,6 +168,7 @@ contract REVLoansUnsourcedTests is TestBaseWorkflow {
139
168
 
140
169
  // The project's revnet configuration
141
170
  REVConfig memory revnetConfiguration = REVConfig({
171
+ // forge-lint: disable-next-line(named-struct-fields)
142
172
  description: REVDescription(name, symbol, projectUri, ERC20_SALT),
143
173
  baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
144
174
  splitOperator: multisig(),
@@ -185,7 +215,11 @@ contract REVLoansUnsourcedTests is TestBaseWorkflow {
185
215
  {
186
216
  REVAutoIssuance[] memory issuanceConfs = new REVAutoIssuance[](1);
187
217
  issuanceConfs[0] = REVAutoIssuance({
188
- 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()
189
223
  });
190
224
 
191
225
  stageConfigurations[0] = REVStageConfig({
@@ -193,6 +227,7 @@ contract REVLoansUnsourcedTests is TestBaseWorkflow {
193
227
  autoIssuances: issuanceConfs,
194
228
  splitPercent: 2000, // 20%
195
229
  splits: splits,
230
+ // forge-lint: disable-next-line(unsafe-typecast)
196
231
  initialIssuance: uint112(1000 * decimalMultiplier),
197
232
  issuanceCutFrequency: 90 days,
198
233
  issuanceCutPercent: JBConstants.MAX_WEIGHT_CUT_PERCENT / 2,
@@ -227,6 +262,7 @@ contract REVLoansUnsourcedTests is TestBaseWorkflow {
227
262
 
228
263
  // The project's revnet configuration
229
264
  REVConfig memory revnetConfiguration = REVConfig({
265
+ // forge-lint: disable-next-line(named-struct-fields)
230
266
  description: REVDescription(name, symbol, projectUri, "NANA_TOKEN"),
231
267
  baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
232
268
  splitOperator: multisig(),
@@ -329,7 +365,15 @@ contract REVLoansUnsourcedTests is TestBaseWorkflow {
329
365
 
330
366
  // Loan fund access limits are now auto-derived from terminal configs, so the surplus allowance exists.
331
367
  // The borrow still fails because USER hasn't approved LOANS to burn their tokens as collateral.
332
- 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
+ );
333
377
 
334
378
  REVLoanSource memory sauce = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: jbMultiTerminal()});
335
379
 
@@ -1,28 +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";
10
14
  import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
11
- import {REVCroptopAllowedPost} from "../src/structs/REVCroptopAllowedPost.sol";
12
15
 
16
+ // forge-lint: disable-next-line(unaliased-plain-import)
13
17
  import "@bananapus/core-v6/script/helpers/CoreDeploymentLib.sol";
18
+ // forge-lint: disable-next-line(unaliased-plain-import)
14
19
  import "@bananapus/721-hook-v6/script/helpers/Hook721DeploymentLib.sol";
20
+ // forge-lint: disable-next-line(unaliased-plain-import)
15
21
  import "@bananapus/suckers-v6/script/helpers/SuckerDeploymentLib.sol";
22
+ // forge-lint: disable-next-line(unaliased-plain-import)
16
23
  import "@croptop/core-v6/script/helpers/CroptopDeploymentLib.sol";
24
+ // forge-lint: disable-next-line(unaliased-plain-import)
17
25
  import "@bananapus/router-terminal-v6/script/helpers/RouterTerminalDeploymentLib.sol";
18
26
  import {JBConstants} from "@bananapus/core-v6/src/libraries/JBConstants.sol";
19
27
  import {JBAccountingContext} from "@bananapus/core-v6/src/structs/JBAccountingContext.sol";
20
- import {MockPriceFeed} from "@bananapus/core-v6/test/mock/MockPriceFeed.sol";
21
28
  import {MockERC20} from "@bananapus/core-v6/test/mock/MockERC20.sol";
22
29
  import {REVLoans} from "../src/REVLoans.sol";
23
- import {REVLoan} from "../src/structs/REVLoan.sol";
24
30
  import {REVStageConfig, REVAutoIssuance} from "../src/structs/REVStageConfig.sol";
25
- import {REVLoanSource} from "../src/structs/REVLoanSource.sol";
26
31
  import {REVDescription} from "../src/structs/REVDescription.sol";
27
32
  import {IREVLoans} from "./../src/interfaces/IREVLoans.sol";
28
33
  import {JBSuckerDeployerConfig} from "@bananapus/suckers-v6/src/structs/JBSuckerDeployerConfig.sol";
@@ -40,24 +45,40 @@ struct FeeProjectConfig {
40
45
  }
41
46
 
42
47
  contract TestBurnHeldTokens is TestBaseWorkflow {
48
+ // forge-lint: disable-next-line(mixed-case-variable)
43
49
  bytes32 REV_DEPLOYER_SALT = "REVDeployer";
50
+ // forge-lint: disable-next-line(mixed-case-variable)
44
51
  bytes32 ERC20_SALT = "REV_TOKEN";
45
52
 
53
+ // forge-lint: disable-next-line(mixed-case-variable)
46
54
  REVDeployer REV_DEPLOYER;
55
+ // forge-lint: disable-next-line(mixed-case-variable)
47
56
  JB721TiersHook EXAMPLE_HOOK;
57
+ // forge-lint: disable-next-line(mixed-case-variable)
48
58
  IJB721TiersHookDeployer HOOK_DEPLOYER;
59
+ // forge-lint: disable-next-line(mixed-case-variable)
49
60
  IJB721TiersHookStore HOOK_STORE;
61
+ // forge-lint: disable-next-line(mixed-case-variable)
50
62
  IJBAddressRegistry ADDRESS_REGISTRY;
63
+ // forge-lint: disable-next-line(mixed-case-variable)
51
64
  IREVLoans LOANS_CONTRACT;
65
+ // forge-lint: disable-next-line(mixed-case-variable)
52
66
  MockERC20 TOKEN;
67
+ // forge-lint: disable-next-line(mixed-case-variable)
53
68
  IJBSuckerRegistry SUCKER_REGISTRY;
69
+ // forge-lint: disable-next-line(mixed-case-variable)
54
70
  CTPublisher PUBLISHER;
71
+ // forge-lint: disable-next-line(mixed-case-variable)
55
72
  MockBuybackDataHook MOCK_BUYBACK;
56
73
 
74
+ // forge-lint: disable-next-line(mixed-case-variable)
57
75
  uint256 FEE_PROJECT_ID;
76
+ // forge-lint: disable-next-line(mixed-case-variable)
58
77
  uint256 REVNET_ID;
59
78
 
79
+ // forge-lint: disable-next-line(mixed-case-variable)
60
80
  address USER = makeAddr("user");
81
+ // forge-lint: disable-next-line(mixed-case-variable)
61
82
  address RANDOM_CALLER = makeAddr("randomCaller");
62
83
 
63
84
  address private constant TRUSTED_FORWARDER = 0xB2b5841DBeF766d4b521221732F9B618fCf34A87;
@@ -85,6 +106,7 @@ contract TestBurnHeldTokens is TestBaseWorkflow {
85
106
  autoIssuances: new REVAutoIssuance[](0),
86
107
  splitPercent: 2000,
87
108
  splits: splits,
109
+ // forge-lint: disable-next-line(unsafe-typecast)
88
110
  initialIssuance: uint112(1000 * decimalMultiplier),
89
111
  issuanceCutFrequency: 90 days,
90
112
  issuanceCutPercent: JBConstants.MAX_WEIGHT_CUT_PERCENT / 2,
@@ -93,6 +115,7 @@ contract TestBurnHeldTokens is TestBaseWorkflow {
93
115
  });
94
116
 
95
117
  REVConfig memory revnetConfiguration = REVConfig({
118
+ // forge-lint: disable-next-line(named-struct-fields)
96
119
  description: REVDescription("Revnet", "$REV", "ipfs://test", ERC20_SALT),
97
120
  baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
98
121
  splitOperator: multisig(),
@@ -135,6 +158,7 @@ contract TestBurnHeldTokens is TestBaseWorkflow {
135
158
  autoIssuances: new REVAutoIssuance[](0),
136
159
  splitPercent: 2000, // 20% reserved
137
160
  splits: splits,
161
+ // forge-lint: disable-next-line(unsafe-typecast)
138
162
  initialIssuance: uint112(1000 * decimalMultiplier),
139
163
  issuanceCutFrequency: 0,
140
164
  issuanceCutPercent: 0,
@@ -143,6 +167,7 @@ contract TestBurnHeldTokens is TestBaseWorkflow {
143
167
  });
144
168
 
145
169
  REVConfig memory revnetConfiguration = REVConfig({
170
+ // forge-lint: disable-next-line(named-struct-fields)
146
171
  description: REVDescription("Partial", "$PRT", "ipfs://test", "PRT_TOKEN"),
147
172
  baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
148
173
  splitOperator: multisig(),
@@ -290,6 +315,7 @@ contract TestBurnHeldTokens is TestBaseWorkflow {
290
315
  autoIssuances: new REVAutoIssuance[](0),
291
316
  splitPercent: 2000,
292
317
  splits: splits,
318
+ // forge-lint: disable-next-line(unsafe-typecast)
293
319
  initialIssuance: uint112(1000 * decimalMultiplier),
294
320
  issuanceCutFrequency: 0,
295
321
  issuanceCutPercent: 0,
@@ -300,6 +326,7 @@ contract TestBurnHeldTokens is TestBaseWorkflow {
300
326
  (uint256 fullSplitRevnetId,) = REV_DEPLOYER.deployFor({
301
327
  revnetId: 0,
302
328
  configuration: REVConfig({
329
+ // forge-lint: disable-next-line(named-struct-fields)
303
330
  description: REVDescription("Full", "$FUL", "ipfs://test", "FUL_TOKEN"),
304
331
  baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
305
332
  splitOperator: multisig(),
@@ -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
  import {JBConstants} from "@bananapus/core-v6/src/libraries/JBConstants.sol";
17
26
  import {JBAccountingContext} from "@bananapus/core-v6/src/structs/JBAccountingContext.sol";
@@ -31,7 +40,6 @@ import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStor
31
40
  import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
32
41
  import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
33
42
  import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
34
- import {REVCroptopAllowedPost} from "../src/structs/REVCroptopAllowedPost.sol";
35
43
 
36
44
  /// @notice Contract that reenters REVLoans when it receives ETH during a borrow payout.
37
45
  /// Records the loan state it observes during reentrancy to verify CEI correctness.
@@ -72,22 +80,36 @@ contract ReentrantBorrower {
72
80
  /// None of the four helpers read loan.amount or loan.collateral — they all use pre-computed deltas.
73
81
  /// The CEI fix writes loan.amount and loan.collateral BEFORE calling any of these helpers.
74
82
  contract TestCEIPattern is TestBaseWorkflow {
83
+ // forge-lint: disable-next-line(mixed-case-variable)
75
84
  bytes32 REV_DEPLOYER_SALT = "REVDeployer";
76
85
 
86
+ // forge-lint: disable-next-line(mixed-case-variable)
77
87
  REVDeployer REV_DEPLOYER;
88
+ // forge-lint: disable-next-line(mixed-case-variable)
78
89
  JB721TiersHook EXAMPLE_HOOK;
90
+ // forge-lint: disable-next-line(mixed-case-variable)
79
91
  IJB721TiersHookDeployer HOOK_DEPLOYER;
92
+ // forge-lint: disable-next-line(mixed-case-variable)
80
93
  IJB721TiersHookStore HOOK_STORE;
94
+ // forge-lint: disable-next-line(mixed-case-variable)
81
95
  IJBAddressRegistry ADDRESS_REGISTRY;
96
+ // forge-lint: disable-next-line(mixed-case-variable)
82
97
  IREVLoans LOANS_CONTRACT;
98
+ // forge-lint: disable-next-line(mixed-case-variable)
83
99
  MockERC20 TOKEN;
100
+ // forge-lint: disable-next-line(mixed-case-variable)
84
101
  IJBSuckerRegistry SUCKER_REGISTRY;
102
+ // forge-lint: disable-next-line(mixed-case-variable)
85
103
  CTPublisher PUBLISHER;
104
+ // forge-lint: disable-next-line(mixed-case-variable)
86
105
  MockBuybackDataHook MOCK_BUYBACK;
87
106
 
107
+ // forge-lint: disable-next-line(mixed-case-variable)
88
108
  uint256 FEE_PROJECT_ID;
109
+ // forge-lint: disable-next-line(mixed-case-variable)
89
110
  uint256 REVNET_ID;
90
111
 
112
+ // forge-lint: disable-next-line(mixed-case-variable)
91
113
  address USER = makeAddr("user");
92
114
  address private constant TRUSTED_FORWARDER = 0xB2b5841DBeF766d4b521221732F9B618fCf34A87;
93
115
 
@@ -159,6 +181,7 @@ contract TestCEIPattern is TestBaseWorkflow {
159
181
  extraMetadata: 0
160
182
  });
161
183
  REVConfig memory cfg = REVConfig({
184
+ // forge-lint: disable-next-line(named-struct-fields)
162
185
  description: REVDescription("Revnet", "$REV", "ipfs://test", "REV_TOKEN"),
163
186
  baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
164
187
  splitOperator: multisig(),
@@ -205,6 +228,7 @@ contract TestCEIPattern is TestBaseWorkflow {
205
228
  REVLoanSource[] memory ls = new REVLoanSource[](1);
206
229
  ls[0] = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: jbMultiTerminal()});
207
230
  REVConfig memory cfg = REVConfig({
231
+ // forge-lint: disable-next-line(named-struct-fields)
208
232
  description: REVDescription("NANA", "$NANA", "ipfs://test2", "NANA_TOKEN"),
209
233
  baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
210
234
  splitOperator: multisig(),