@rev-net/core-v6 0.0.9 → 0.0.11

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 (46) hide show
  1. package/ARCHITECTURE.md +1 -1
  2. package/README.md +4 -4
  3. package/SKILLS.md +2 -8
  4. package/STYLE_GUIDE.md +127 -51
  5. package/docs/src/README.md +2 -2
  6. package/foundry.toml +3 -0
  7. package/package.json +12 -9
  8. package/remappings.txt +1 -1
  9. package/script/Deploy.s.sol +1 -1
  10. package/script/helpers/RevnetCoreDeploymentLib.sol +1 -1
  11. package/src/REVDeployer.sol +30 -26
  12. package/src/REVLoans.sol +1 -0
  13. package/test/{REVDeployerAuditRegressions.t.sol → REVDeployerRegressions.t.sol} +1 -1
  14. package/test/REVInvincibility.t.sol +15 -19
  15. package/test/REVLifecycle.t.sol +0 -1
  16. package/test/REVLoansAttacks.t.sol +3 -7
  17. package/test/REVLoansFeeRecovery.t.sol +0 -2
  18. package/test/{REVLoans_AuditFindings.t.sol → REVLoansFindings.t.sol} +6 -6
  19. package/test/{REVLoansAuditRegressions.t.sol → REVLoansRegressions.t.sol} +2 -2
  20. package/test/REVLoansSourced.t.sol +3 -1
  21. package/test/{TestPR26_BurnHeldTokens.t.sol → TestBurnHeldTokens.t.sol} +1 -1
  22. package/test/{TestPR27_CEIPattern.t.sol → TestCEIPattern.t.sol} +3 -3
  23. package/test/{TestPR15_CashOutCallerValidation.t.sol → TestCashOutCallerValidation.t.sol} +1 -3
  24. package/test/{TestPR09_ConversionDocumentation.t.sol → TestConversionDocumentation.t.sol} +1 -1
  25. package/test/{TestPR13_CrossSourceReallocation.t.sol → TestCrossSourceReallocation.t.sol} +1 -1
  26. package/test/{TestPR12_FlashLoanSurplus.t.sol → TestFlashLoanSurplus.t.sol} +1 -1
  27. package/test/{TestPR22_HookArrayOOB.t.sol → TestHookArrayOOB.t.sol} +1 -1
  28. package/test/{TestPR10_LiquidationBehavior.t.sol → TestLiquidationBehavior.t.sol} +4 -4
  29. package/test/{TestPR11_LowFindings.t.sol → TestLowFindings.t.sol} +1 -1
  30. package/test/{TestPR32_MixedFixes.t.sol → TestMixedFixes.t.sol} +1 -1
  31. package/test/TestSplitWeightFork.t.sol +118 -159
  32. package/test/{TestPR29_SwapTerminalPermission.t.sol → TestSwapTerminalPermission.t.sol} +1 -1
  33. package/test/{TestPR21_Uint112Overflow.t.sol → TestUint112Overflow.t.sol} +4 -4
  34. package/test/{TestPR16_ZeroRepayment.t.sol → TestZeroRepayment.t.sol} +4 -6
  35. package/test/fork/ForkTestBase.sol +83 -51
  36. package/test/fork/TestCashOutFork.t.sol +12 -11
  37. package/test/fork/TestLoanBorrowFork.t.sol +10 -12
  38. package/test/fork/TestLoanCrossRulesetFork.t.sol +300 -0
  39. package/test/fork/TestLoanLiquidationFork.t.sol +13 -8
  40. package/test/fork/TestLoanReallocateFork.t.sol +21 -12
  41. package/test/fork/TestLoanRepayFork.t.sol +17 -14
  42. package/test/fork/TestSplitWeightFork.t.sol +34 -34
  43. package/test/mock/MockBuybackDataHook.sol +4 -7
  44. package/test/mock/MockBuybackDataHookMintPath.sol +5 -8
  45. package/test/regression/{TestI20_CumulativeLoanCounter.t.sol → TestCumulativeLoanCounter.t.sol} +4 -4
  46. package/test/regression/{TestL27_LiquidateGapHandling.t.sol → TestLiquidateGapHandling.t.sol} +3 -3
@@ -373,7 +373,7 @@ contract REVInvincibility_PropertyTests is TestBaseWorkflow {
373
373
  /// @notice hasMintPermissionFor returns false for random addresses.
374
374
  /// @dev With the buyback hook removed, hasMintPermissionFor should return false
375
375
  /// for addresses that are not the loans contract or a sucker.
376
- function test_fixVerify_hasMintPermission_noBuyback() public {
376
+ function test_fixVerify_hasMintPermission_noBuyback() public view {
377
377
  // The fee project was deployed without buyback hook in our setup
378
378
  JBRuleset memory currentRuleset = jbRulesets().currentOf(FEE_PROJECT_ID);
379
379
 
@@ -574,7 +574,7 @@ contract REVInvincibility_PropertyTests is TestBaseWorkflow {
574
574
  function test_econ_loanAmplificationSpiral() public {
575
575
  // Step 1: Pay to get tokens
576
576
  uint256 payAmount = 10e18;
577
- (uint256 loanId1, uint256 tokens1, uint256 borrow1) = _setupLoan(USER, payAmount, 25);
577
+ (,, uint256 borrow1) = _setupLoan(USER, payAmount, 25);
578
578
  assertTrue(borrow1 > 0, "First loan should have borrow amount");
579
579
 
580
580
  // Step 2: Add borrowed amount back to balance (inflating surplus)
@@ -588,8 +588,7 @@ contract REVInvincibility_PropertyTests is TestBaseWorkflow {
588
588
  jbMultiTerminal().pay{value: payAmount}(REVNET_ID, JBConstants.NATIVE_TOKEN, payAmount, USER, 0, "", "");
589
589
 
590
590
  // Step 4: Try to borrow again
591
- uint256 borrowable2 =
592
- LOANS_CONTRACT.borrowableAmountFrom(REVNET_ID, tokens2, 18, uint32(uint160(JBConstants.NATIVE_TOKEN)));
591
+ LOANS_CONTRACT.borrowableAmountFrom(REVNET_ID, tokens2, 18, uint32(uint160(JBConstants.NATIVE_TOKEN)));
593
592
 
594
593
  // The totalBorrowed from loan1 is added to surplus in borrowableAmountFrom,
595
594
  // so the second borrow should not amplify beyond what the real surplus supports.
@@ -619,7 +618,7 @@ contract REVInvincibility_PropertyTests is TestBaseWorkflow {
619
618
  jbMultiTerminal().pay{value: 0.01e18}(REVNET_ID, JBConstants.NATIVE_TOKEN, 0.01e18, payor, 0, "", "");
620
619
 
621
620
  // Get current ruleset to verify we're in stage 1
622
- JBRuleset memory currentRuleset = jbRulesets().currentOf(REVNET_ID);
621
+ jbRulesets().currentOf(REVNET_ID);
623
622
 
624
623
  // Cash out at the new (lower) tax rate
625
624
  // Note: there's a 30-day cash out delay, so we advance more
@@ -653,8 +652,7 @@ contract REVInvincibility_PropertyTests is TestBaseWorkflow {
653
652
  function test_econ_reservedTokenDilution() public {
654
653
  // Pay to create surplus + mint tokens (some go to reserved)
655
654
  vm.prank(USER);
656
- uint256 userTokens =
657
- jbMultiTerminal().pay{value: 10e18}(REVNET_ID, JBConstants.NATIVE_TOKEN, 10e18, USER, 0, "", "");
655
+ jbMultiTerminal().pay{value: 10e18}(REVNET_ID, JBConstants.NATIVE_TOKEN, 10e18, USER, 0, "", "");
658
656
 
659
657
  // Send reserved tokens to splits
660
658
  try jbController().sendReservedTokensToSplitsOf(REVNET_ID) {} catch {}
@@ -721,8 +719,7 @@ contract REVInvincibility_PropertyTests is TestBaseWorkflow {
721
719
  jbMultiTerminal().pay{value: 10e18}(REVNET_ID, JBConstants.NATIVE_TOKEN, 10e18, userA, 0, "", "");
722
720
 
723
721
  vm.prank(userB);
724
- uint256 tokensB =
725
- jbMultiTerminal().pay{value: 10e18}(REVNET_ID, JBConstants.NATIVE_TOKEN, 10e18, userB, 0, "", "");
722
+ jbMultiTerminal().pay{value: 10e18}(REVNET_ID, JBConstants.NATIVE_TOKEN, 10e18, userB, 0, "", "");
726
723
 
727
724
  // UserA borrows (tokens locked as collateral)
728
725
  mockExpect(
@@ -757,7 +754,7 @@ contract REVInvincibility_PropertyTests is TestBaseWorkflow {
757
754
  /// @dev Extraction should be bounded by the bonding curve.
758
755
  function test_econ_collateralRotation() public {
759
756
  // Setup initial loan
760
- (uint256 loanId, uint256 tokens, uint256 borrowAmount) = _setupLoan(USER, 5e18, 25);
757
+ (uint256 loanId,, uint256 borrowAmount) = _setupLoan(USER, 5e18, 25);
761
758
  if (borrowAmount == 0) return;
762
759
 
763
760
  // Surplus increases (someone else pays in)
@@ -787,7 +784,7 @@ contract REVInvincibility_PropertyTests is TestBaseWorkflow {
787
784
  /// @dev Borrow all available surplus → new payments and repayment still functional.
788
785
  function test_econ_zeroSurplusLoanDefault() public {
789
786
  // Pay and borrow maximum
790
- (uint256 loanId, uint256 tokens, uint256 borrowAmount) = _setupLoan(USER, 10e18, 25);
787
+ (,, uint256 borrowAmount) = _setupLoan(USER, 10e18, 25);
791
788
  if (borrowAmount == 0) return;
792
789
 
793
790
  // New user can still pay into the system
@@ -802,7 +799,7 @@ contract REVInvincibility_PropertyTests is TestBaseWorkflow {
802
799
  /// @notice Loans across stage boundary: loans stay healthy when tax rate decreases.
803
800
  function test_econ_stageTransitionWithLoans() public {
804
801
  // Create loan in stage 0
805
- (uint256 loanId, uint256 tokens, uint256 borrowAmount) = _setupLoan(USER, 10e18, 25);
802
+ (uint256 loanId,, uint256 borrowAmount) = _setupLoan(USER, 10e18, 25);
806
803
  if (borrowAmount == 0) return;
807
804
 
808
805
  REVLoan memory loanBefore = LOANS_CONTRACT.loanOf(loanId);
@@ -822,7 +819,7 @@ contract REVInvincibility_PropertyTests is TestBaseWorkflow {
822
819
  assertEq(loanAfter.collateral, loanBefore.collateral, "Loan collateral unchanged across stages");
823
820
 
824
821
  // Borrowable amount may have changed (different tax rate)
825
- uint256 newBorrowable = LOANS_CONTRACT.borrowableAmountFrom(
822
+ LOANS_CONTRACT.borrowableAmountFrom(
826
823
  REVNET_ID, loanAfter.collateral, 18, uint32(uint160(JBConstants.NATIVE_TOKEN))
827
824
  );
828
825
  // With lower tax rate in stage 1, borrowable should increase
@@ -834,8 +831,7 @@ contract REVInvincibility_PropertyTests is TestBaseWorkflow {
834
831
  function test_econ_splitOperatorRug() public {
835
832
  // Pay to build up surplus and reserved tokens
836
833
  vm.prank(USER);
837
- uint256 userTokens =
838
- jbMultiTerminal().pay{value: 50e18}(REVNET_ID, JBConstants.NATIVE_TOKEN, 50e18, USER, 0, "", "");
834
+ jbMultiTerminal().pay{value: 50e18}(REVNET_ID, JBConstants.NATIVE_TOKEN, 50e18, USER, 0, "", "");
839
835
 
840
836
  // Send reserved tokens to splits (multisig = split beneficiary)
841
837
  try jbController().sendReservedTokensToSplitsOf(REVNET_ID) {} catch {}
@@ -1168,7 +1164,7 @@ contract REVInvincibility_Invariants is StdInvariant, TestBaseWorkflow {
1168
1164
  // INV-REV-2: Collateral accounting exact
1169
1165
  // =====================================================================
1170
1166
  /// @notice Ghost collateral sum must match contract's totalCollateralOf.
1171
- function invariant_REV_2_collateralAccountingExact() public {
1167
+ function invariant_REV_2_collateralAccountingExact() public view {
1172
1168
  assertEq(
1173
1169
  HANDLER.COLLATERAL_SUM(),
1174
1170
  LOANS_CONTRACT.totalCollateralOf(REVNET_ID),
@@ -1180,7 +1176,7 @@ contract REVInvincibility_Invariants is StdInvariant, TestBaseWorkflow {
1180
1176
  // INV-REV-3: Borrow accounting exact
1181
1177
  // =====================================================================
1182
1178
  /// @notice Ghost borrowed sum must match contract's totalBorrowedFrom.
1183
- function invariant_REV_3_borrowAccountingExact() public {
1179
+ function invariant_REV_3_borrowAccountingExact() public view {
1184
1180
  uint256 actualTotalBorrowed =
1185
1181
  LOANS_CONTRACT.totalBorrowedFrom(REVNET_ID, jbMultiTerminal(), JBConstants.NATIVE_TOKEN);
1186
1182
 
@@ -1196,7 +1192,7 @@ contract REVInvincibility_Invariants is StdInvariant, TestBaseWorkflow {
1196
1192
  /// @dev Loans CAN become undercollateralized when new payments increase totalSupply
1197
1193
  /// faster than surplus grows (bonding curve dilution). This is expected behavior.
1198
1194
  /// We verify that the loan struct itself is internally consistent.
1199
- function invariant_REV_4_noUndercollateralizedLoans() public {
1195
+ function invariant_REV_4_noUndercollateralizedLoans() public view {
1200
1196
  if (HANDLER.callCount_payAndBorrow() == 0) return;
1201
1197
 
1202
1198
  for (uint256 i = 1; i <= HANDLER.callCount_payAndBorrow(); i++) {
@@ -1226,7 +1222,7 @@ contract REVInvincibility_Invariants is StdInvariant, TestBaseWorkflow {
1226
1222
  // INV-REV-5: Supply + collateral consistency
1227
1223
  // =====================================================================
1228
1224
  /// @notice totalSupply + totalCollateral should be coherent with token tracking.
1229
- function invariant_REV_5_supplyCollateralConsistency() public {
1225
+ function invariant_REV_5_supplyCollateralConsistency() public view {
1230
1226
  uint256 totalSupply = jbController().totalTokenSupplyWithReservedTokensOf(REVNET_ID);
1231
1227
  uint256 totalCollateral = LOANS_CONTRACT.totalCollateralOf(REVNET_ID);
1232
1228
 
@@ -252,7 +252,6 @@ contract REVLifecycle_Local is TestBaseWorkflow {
252
252
 
253
253
  // Cash out half in stage 0 (50% tax)
254
254
  uint256 halfTokens = tokens / 2;
255
- uint256 user1BalBefore = USER1.balance;
256
255
  vm.prank(USER1);
257
256
  uint256 reclaimedStage0 = jbMultiTerminal()
258
257
  .cashOutTokensOf({
@@ -524,7 +524,7 @@ contract REVLoansAttacks is TestBaseWorkflow {
524
524
 
525
525
  // Setup: create a loan first
526
526
  uint256 payAmount = 10e18;
527
- (uint256 loanId, uint256 tokenCount, uint256 borrowAmount) = _setupLoan(USER, payAmount, 25);
527
+ (uint256 loanId,, uint256 borrowAmount) = _setupLoan(USER, payAmount, 25);
528
528
  vm.assume(borrowAmount > 0);
529
529
 
530
530
  // The loan exists. The reentrancy risk during repayLoan:
@@ -559,8 +559,7 @@ contract REVLoansAttacks is TestBaseWorkflow {
559
559
  jbMultiTerminal().pay{value: 10e18}(REVNET_ID, JBConstants.NATIVE_TOKEN, 10e18, userA, 0, "", "");
560
560
 
561
561
  vm.prank(userB);
562
- uint256 tokensB =
563
- jbMultiTerminal().pay{value: 10e18}(REVNET_ID, JBConstants.NATIVE_TOKEN, 10e18, userB, 0, "", "");
562
+ jbMultiTerminal().pay{value: 10e18}(REVNET_ID, JBConstants.NATIVE_TOKEN, 10e18, userB, 0, "", "");
564
563
 
565
564
  // Record pre-borrow state
566
565
  uint256 totalSupplyBefore = jbController().totalTokenSupplyWithReservedTokensOf(REVNET_ID);
@@ -604,7 +603,7 @@ contract REVLoansAttacks is TestBaseWorkflow {
604
603
  /// @notice After LOAN_LIQUIDATION_DURATION (3650 days), the loan expires and cannot be repaid.
605
604
  function test_liquidation_borrowRepayAfterExpiry() public {
606
605
  uint256 payAmount = 10e18;
607
- (uint256 loanId, uint256 tokenCount, uint256 borrowAmount) = _setupLoan(USER, payAmount, 25);
606
+ (uint256 loanId,, uint256 borrowAmount) = _setupLoan(USER, payAmount, 25);
608
607
  vm.assume(borrowAmount > 0);
609
608
 
610
609
  // Warp past the liquidation duration (3650 days)
@@ -715,9 +714,6 @@ contract REVLoansAttacks is TestBaseWorkflow {
715
714
  // Calculate repay amount
716
715
  uint256 repayAmount = loan.amount;
717
716
 
718
- // The user needs to have ETH to repay
719
- uint256 userBalanceBefore = USER.balance;
720
-
721
717
  // Repay the full loan
722
718
  vm.prank(USER);
723
719
  LOANS_CONTRACT.repayLoan{value: repayAmount}({
@@ -195,8 +195,6 @@ contract REVLoansFeeRecovery is TestBaseWorkflow {
195
195
  extraMetadata: 0
196
196
  });
197
197
 
198
- REVLoanSource[] memory _loanSources = new REVLoanSource[](0);
199
-
200
198
  REVConfig memory revnetConfiguration = REVConfig({
201
199
  description: REVDescription(
202
200
  "Revnet", "$REV", "ipfs://QmNRHT91HcDgMcenebYX7rJigt77cgNcosvuhX21wkF3tx", ERC20_SALT
@@ -129,12 +129,12 @@ contract GarbageTerminal is ERC165, IJBPayoutTerminal {
129
129
  receive() external payable {}
130
130
  }
131
131
 
132
- /// @notice Regression tests for nemesis audit findings.
132
+ /// @notice Regression tests for loan findings.
133
133
  /// Unvalidated loan source terminal
134
134
  /// RepayLoan event emits zeroed values
135
135
  /// Auto-issuance timing guard bypass (false positive)
136
136
  /// repayLoan revert on excess collateral (false positive)
137
- contract REVLoans_AuditFindings is TestBaseWorkflow {
137
+ contract REVLoansFindings is TestBaseWorkflow {
138
138
  bytes32 REV_DEPLOYER_SALT = "REVDeployer";
139
139
  bytes32 ERC20_SALT = "REV_TOKEN";
140
140
 
@@ -327,7 +327,7 @@ contract REVLoans_AuditFindings is TestBaseWorkflow {
327
327
  //*********************************************************************//
328
328
 
329
329
  /// @notice borrowFrom rejects a fake terminal not registered in the directory.
330
- function test_H1_borrowFromRejectsUnregisteredTerminal() public {
330
+ function test_borrowFromRejectsUnregisteredTerminal() public {
331
331
  // Step 1: User pays into the revnet to get tokens.
332
332
  uint256 tokens = _payAndGetTokens(1e18);
333
333
  assertGt(tokens, 0, "user should receive tokens");
@@ -367,10 +367,10 @@ contract REVLoans_AuditFindings is TestBaseWorkflow {
367
367
 
368
368
  /// @notice RepayLoan event emits non-zero loan amount and collateral
369
369
  /// when fully repaying a loan.
370
- function test_L1_repayLoanEventEmitsNonZeroValues() public {
370
+ function test_repayLoanEventEmitsNonZeroValues() public {
371
371
  // Step 1: Pay in and borrow.
372
372
  uint256 tokens = _payAndGetTokens(1e18);
373
- (uint256 loanId, REVLoan memory loan, uint256 loanable) = _borrow(tokens);
373
+ (uint256 loanId, REVLoan memory loan,) = _borrow(tokens);
374
374
 
375
375
  assertGt(loan.amount, 0, "loan amount should be non-zero");
376
376
  assertGt(loan.collateral, 0, "loan collateral should be non-zero");
@@ -408,7 +408,7 @@ contract REVLoans_AuditFindings is TestBaseWorkflow {
408
408
 
409
409
  /// @notice Secondary check: verify the original loan data in the emitted event
410
410
  /// has the expected non-zero amount and collateral by recording logs.
411
- function test_L1_repayLoanEventLoanFieldIsNonZero() public {
411
+ function test_repayLoanEventLoanFieldIsNonZero() public {
412
412
  // Step 1: Pay in and borrow.
413
413
  uint256 tokens = _payAndGetTokens(1e18);
414
414
  (uint256 loanId, REVLoan memory loan,) = _borrow(tokens);
@@ -129,7 +129,7 @@ contract FakeTerminal is ERC165, IJBPayoutTerminal {
129
129
  }
130
130
 
131
131
  /// @notice Regression tests for REVLoans unvalidated source terminal.
132
- contract REVLoansRegressions_Local is TestBaseWorkflow {
132
+ contract REVLoansRegressions is TestBaseWorkflow {
133
133
  bytes32 REV_DEPLOYER_SALT = "REVDeployer";
134
134
  bytes32 ERC20_SALT = "REV_TOKEN";
135
135
 
@@ -289,7 +289,7 @@ contract REVLoansRegressions_Local is TestBaseWorkflow {
289
289
  }
290
290
 
291
291
  /// @notice Verify that the configured loan source (real terminal) is properly registered.
292
- function test_configuredSourceIsRegistered() public {
292
+ function test_configuredSourceIsRegistered() public view {
293
293
  // The real terminal should be in the directory
294
294
  IJBTerminal[] memory terminals = jbDirectory().terminalsOf(REVNET_ID);
295
295
  bool found = false;
@@ -729,7 +729,9 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
729
729
 
730
730
  assertApproxEqAbs(balance, reclaimableSurplus - nanaFee, 1);
731
731
 
732
- assertGe(reclaimableSurplus + revFee, mulDiv(loanable, 97, 100)); // small marging for curve rounding.
732
+ // Allow 2 wei absolute tolerance alongside 3% relative tolerance at very small
733
+ // surplus values (e.g. 90 wei), a single mulDiv rounding error exceeds 3%.
734
+ assertGe(reclaimableSurplus + revFee + 2, mulDiv(loanable, 97, 100));
733
735
  }
734
736
 
735
737
  function test_Pay_Borrow_With_Loan_Source() public {
@@ -37,7 +37,7 @@ struct FeeProjectConfig {
37
37
  REVSuckerDeploymentConfig suckerDeploymentConfiguration;
38
38
  }
39
39
 
40
- contract TestPR26_BurnHeldTokens is TestBaseWorkflow {
40
+ contract TestBurnHeldTokens is TestBaseWorkflow {
41
41
  bytes32 REV_DEPLOYER_SALT = "REVDeployer";
42
42
  bytes32 ERC20_SALT = "REV_TOKEN";
43
43
 
@@ -59,7 +59,7 @@ contract ReentrantBorrower {
59
59
  }
60
60
  }
61
61
 
62
- /// @title TestPR27_CEIPattern
62
+ /// @title TestCEIPattern
63
63
  /// @notice Tests for CEI pattern fix in REVLoans._adjust()
64
64
  ///
65
65
  /// Source context (_addTo/_removeFrom/_addCollateralTo/_returnCollateralFrom):
@@ -69,7 +69,7 @@ contract ReentrantBorrower {
69
69
  /// - _returnCollateralFrom(uint256 revnetId, uint256 collateralCount, ...) — no loan reference
70
70
  /// None of the four helpers read loan.amount or loan.collateral — they all use pre-computed deltas.
71
71
  /// The CEI fix writes loan.amount and loan.collateral BEFORE calling any of these helpers.
72
- contract TestPR27_CEIPattern is TestBaseWorkflow {
72
+ contract TestCEIPattern is TestBaseWorkflow {
73
73
  bytes32 REV_DEPLOYER_SALT = "REVDeployer";
74
74
 
75
75
  REVDeployer REV_DEPLOYER;
@@ -253,7 +253,7 @@ contract TestPR27_CEIPattern is TestBaseWorkflow {
253
253
 
254
254
  /// @notice Repay a loan and verify state is consistent afterwards.
255
255
  function test_repayLoan_stateConsistent() public {
256
- (uint256 loanId, uint256 tokenCount, uint256 borrowAmount) = _setupLoan(USER, 10e18, 500);
256
+ (uint256 loanId,, uint256 borrowAmount) = _setupLoan(USER, 10e18, 500);
257
257
  assertTrue(borrowAmount > 0, "Should borrow nonzero");
258
258
 
259
259
  REVLoan memory loan = LOANS_CONTRACT.loanOf(loanId);
@@ -37,7 +37,7 @@ struct FeeProjectConfig {
37
37
  REVSuckerDeploymentConfig suckerDeploymentConfiguration;
38
38
  }
39
39
 
40
- contract TestPR15_CashOutCallerValidation is TestBaseWorkflow {
40
+ contract TestCashOutCallerValidation is TestBaseWorkflow {
41
41
  bytes32 REV_DEPLOYER_SALT = "REVDeployer";
42
42
  bytes32 ERC20_SALT = "REV_TOKEN";
43
43
 
@@ -96,8 +96,6 @@ contract TestPR15_CashOutCallerValidation is TestBaseWorkflow {
96
96
  });
97
97
  }
98
98
 
99
- REVLoanSource[] memory loanSources = new REVLoanSource[](0);
100
-
101
99
  REVConfig memory revnetConfiguration = REVConfig({
102
100
  description: REVDescription(name, symbol, projectUri, ERC20_SALT),
103
101
  baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
@@ -31,7 +31,7 @@ import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStor
31
31
  import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
32
32
  import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
33
33
 
34
- contract TestPR09_ConversionDocumentation is TestBaseWorkflow {
34
+ contract TestConversionDocumentation is TestBaseWorkflow {
35
35
  bytes32 REV_DEPLOYER_SALT = "REVDeployer";
36
36
  bytes32 ERC20_SALT = "REV_TOKEN";
37
37
 
@@ -31,7 +31,7 @@ import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressReg
31
31
  import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
32
32
 
33
33
  /// @notice Tests for PR #13: cross-source reallocation prevention.
34
- contract TestPR13_CrossSourceReallocation is TestBaseWorkflow {
34
+ contract TestCrossSourceReallocation is TestBaseWorkflow {
35
35
  bytes32 REV_DEPLOYER_SALT = "REVDeployer";
36
36
 
37
37
  REVDeployer REV_DEPLOYER;
@@ -31,7 +31,7 @@ import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressReg
31
31
  import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
32
32
 
33
33
  /// @notice Tests showing that flash loan surplus manipulation is economically unprofitable.
34
- contract TestPR12_FlashLoanSurplus is TestBaseWorkflow {
34
+ contract TestFlashLoanSurplus is TestBaseWorkflow {
35
35
  bytes32 REV_DEPLOYER_SALT = "REVDeployer";
36
36
  bytes32 ERC20_SALT = "REV_TOKEN";
37
37
 
@@ -36,7 +36,7 @@ import {JBRuleset} from "@bananapus/core-v6/src/structs/JBRuleset.sol";
36
36
  /// The bug: `hookSpecifications[1] = buybackHookSpecifications[0]` would revert with OOB
37
37
  /// when there is no tiered 721 hook (array size is 1, not 2).
38
38
  /// The fix: `hookSpecifications[usesTiered721Hook ? 1 : 0] = buybackHookSpecifications[0]`.
39
- contract TestPR22_HookArrayOOB is TestBaseWorkflow {
39
+ contract TestHookArrayOOB is TestBaseWorkflow {
40
40
  bytes32 REV_DEPLOYER_SALT = "REVDeployer";
41
41
 
42
42
  REVDeployer REV_DEPLOYER;
@@ -33,7 +33,7 @@ import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/
33
33
  import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
34
34
 
35
35
  /// @notice Tests for PR #10: liquidation behavior documentation and collateral burn mechanics.
36
- contract TestPR10_LiquidationBehavior is TestBaseWorkflow {
36
+ contract TestLiquidationBehavior is TestBaseWorkflow {
37
37
  bytes32 REV_DEPLOYER_SALT = "REVDeployer";
38
38
 
39
39
  REVDeployer REV_DEPLOYER;
@@ -251,7 +251,7 @@ contract TestPR10_LiquidationBehavior is TestBaseWorkflow {
251
251
  function test_borrowerKeepsBorrowedFunds() public {
252
252
  uint256 userBalanceBefore = USER.balance;
253
253
 
254
- (uint256 loanId,, uint256 borrowAmount) = _setupLoan(USER, 10e18, 25);
254
+ (uint256 loanId,,) = _setupLoan(USER, 10e18, 25);
255
255
  require(loanId != 0, "Loan setup failed");
256
256
 
257
257
  uint256 userBalanceAfter = USER.balance;
@@ -271,7 +271,7 @@ contract TestPR10_LiquidationBehavior is TestBaseWorkflow {
271
271
 
272
272
  /// @notice Repay before expiry returns collateral (re-mints tokens).
273
273
  function test_repayBeforeExpiry_collateralReminted() public {
274
- (uint256 loanId,, uint256 borrowAmount) = _setupLoan(USER, 10e18, 25);
274
+ (uint256 loanId,,) = _setupLoan(USER, 10e18, 25);
275
275
  require(loanId != 0, "Loan setup failed");
276
276
 
277
277
  REVLoan memory loan = LOANS_CONTRACT.loanOf(loanId);
@@ -296,7 +296,7 @@ contract TestPR10_LiquidationBehavior is TestBaseWorkflow {
296
296
 
297
297
  /// @notice After liquidation, the loan NFT is burned and collateral/borrow tracking is decremented.
298
298
  function test_loanDataDeletedAfterLiquidation() public {
299
- (uint256 loanId,, uint256 borrowAmount) = _setupLoan(USER, 10e18, 25);
299
+ (uint256 loanId,,) = _setupLoan(USER, 10e18, 25);
300
300
  require(loanId != 0, "Loan setup failed");
301
301
 
302
302
  REVLoan memory loan = LOANS_CONTRACT.loanOf(loanId);
@@ -37,7 +37,7 @@ struct FeeProjectConfig {
37
37
  REVSuckerDeploymentConfig suckerDeploymentConfiguration;
38
38
  }
39
39
 
40
- contract TestPR11_LowFindings is TestBaseWorkflow {
40
+ contract TestLowFindings is TestBaseWorkflow {
41
41
  bytes32 REV_DEPLOYER_SALT = "REVDeployer";
42
42
  bytes32 ERC20_SALT = "REV_TOKEN";
43
43
 
@@ -31,7 +31,7 @@ import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressReg
31
31
  import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
32
32
 
33
33
  /// @notice Tests for PR #32: liquidation boundary, reallocate msg.value, and decimal normalization fixes.
34
- contract TestPR32_MixedFixes is TestBaseWorkflow {
34
+ contract TestMixedFixes is TestBaseWorkflow {
35
35
  bytes32 REV_DEPLOYER_SALT = "REVDeployer";
36
36
 
37
37
  REVDeployer REV_DEPLOYER;