@rev-net/core-v6 0.0.29 → 0.0.30

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 (71) hide show
  1. package/ADMINISTRATION.md +19 -9
  2. package/ARCHITECTURE.md +3 -0
  3. package/AUDIT_INSTRUCTIONS.md +11 -1
  4. package/CHANGELOG.md +26 -0
  5. package/README.md +1 -0
  6. package/RISKS.md +28 -4
  7. package/SKILLS.md +2 -1
  8. package/USER_JOURNEYS.md +17 -3
  9. package/package.json +2 -2
  10. package/references/operations.md +1 -1
  11. package/script/Deploy.s.sol +25 -6
  12. package/src/REVHiddenTokens.sol +149 -0
  13. package/src/REVLoans.sol +115 -144
  14. package/src/REVOwner.sol +11 -3
  15. package/src/interfaces/IREVHiddenTokens.sol +53 -0
  16. package/src/interfaces/IREVLoans.sol +3 -6
  17. package/test/REV.integrations.t.sol +2 -1
  18. package/test/REVAutoIssuanceFuzz.t.sol +2 -1
  19. package/test/REVDeployerRegressions.t.sol +2 -2
  20. package/test/REVInvincibility.t.sol +6 -6
  21. package/test/REVInvincibilityHandler.sol +1 -1
  22. package/test/REVLifecycle.t.sol +2 -2
  23. package/test/REVLoans.invariants.t.sol +3 -3
  24. package/test/REVLoansAttacks.t.sol +7 -6
  25. package/test/REVLoansFeeRecovery.t.sol +12 -12
  26. package/test/REVLoansFindings.t.sol +4 -4
  27. package/test/REVLoansRegressions.t.sol +3 -3
  28. package/test/REVLoansSourceFeeRecovery.t.sol +4 -4
  29. package/test/REVLoansSourced.t.sol +48 -24
  30. package/test/REVLoansUnSourced.t.sol +3 -3
  31. package/test/TestBurnHeldTokens.t.sol +2 -2
  32. package/test/TestCEIPattern.t.sol +7 -6
  33. package/test/TestCashOutCallerValidation.t.sol +2 -2
  34. package/test/TestConversionDocumentation.t.sol +2 -2
  35. package/test/TestCrossCurrencyReclaim.t.sol +2 -2
  36. package/test/TestCrossSourceReallocation.t.sol +3 -3
  37. package/test/TestERC2771MetaTx.t.sol +6 -4
  38. package/test/TestEmptyBuybackSpecs.t.sol +2 -2
  39. package/test/TestFlashLoanSurplus.t.sol +3 -3
  40. package/test/TestHiddenTokens.t.sol +420 -0
  41. package/test/TestHookArrayOOB.t.sol +2 -2
  42. package/test/TestLiquidationBehavior.t.sol +4 -4
  43. package/test/TestLoanSourceRotation.t.sol +8 -6
  44. package/test/TestLoansCashOutDelay.t.sol +6 -6
  45. package/test/TestLongTailEconomics.t.sol +2 -2
  46. package/test/TestLowFindings.t.sol +13 -8
  47. package/test/TestMixedFixes.t.sol +7 -7
  48. package/test/TestPermit2Signatures.t.sol +3 -3
  49. package/test/TestReallocationSandwich.t.sol +4 -3
  50. package/test/TestRevnetRegressions.t.sol +3 -4
  51. package/test/TestSplitWeightAdjustment.t.sol +4 -3
  52. package/test/TestSplitWeightE2E.t.sol +4 -3
  53. package/test/TestSplitWeightFork.t.sol +2 -2
  54. package/test/TestStageTransitionBorrowable.t.sol +2 -2
  55. package/test/TestSwapTerminalPermission.t.sol +2 -2
  56. package/test/TestUint112Overflow.t.sol +3 -3
  57. package/test/TestZeroAmountLoanGuard.t.sol +3 -3
  58. package/test/TestZeroRepayment.t.sol +3 -3
  59. package/test/audit/LoanIdOverflowGuard.t.sol +4 -4
  60. package/test/audit/NemesisOperatorDelegation.t.sol +278 -0
  61. package/test/fork/ForkTestBase.sol +4 -3
  62. package/test/fork/TestLoanBorrowFork.t.sol +2 -1
  63. package/test/fork/TestLoanERC20Fork.t.sol +4 -2
  64. package/test/fork/TestLoanTransferFork.t.sol +12 -2
  65. package/test/helpers/MaliciousContracts.sol +1 -1
  66. package/test/regression/TestBurnPermissionRequired.t.sol +4 -4
  67. package/test/regression/TestCashOutBuybackFeeLeak.t.sol +2 -2
  68. package/test/regression/TestCrossRevnetLiquidation.t.sol +2 -2
  69. package/test/regression/TestCumulativeLoanCounter.t.sol +3 -3
  70. package/test/regression/TestLiquidateGapHandling.t.sol +3 -3
  71. package/test/regression/TestZeroPriceFeed.t.sol +5 -5
@@ -23,6 +23,8 @@ import "@croptop/core-v6/script/helpers/CroptopDeploymentLib.sol";
23
23
  // forge-lint: disable-next-line(unaliased-plain-import)
24
24
  import "@bananapus/router-terminal-v6/script/helpers/RouterTerminalDeploymentLib.sol";
25
25
 
26
+ import {JBPermissioned} from "@bananapus/core-v6/src/abstract/JBPermissioned.sol";
27
+ import {JBPermissionIds} from "@bananapus/permission-ids-v6/src/JBPermissionIds.sol";
26
28
  import {JBConstants} from "@bananapus/core-v6/src/libraries/JBConstants.sol";
27
29
  import {JBAccountingContext} from "@bananapus/core-v6/src/structs/JBAccountingContext.sol";
28
30
  import {MockPriceFeed} from "@bananapus/core-v6/test/mock/MockPriceFeed.sol";
@@ -328,7 +330,6 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
328
330
 
329
331
  LOANS_CONTRACT = new REVLoans({
330
332
  controller: jbController(),
331
- projects: jbProjects(),
332
333
  revId: FEE_PROJECT_ID,
333
334
  owner: address(this),
334
335
  permit2: permit2(),
@@ -340,7 +341,8 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
340
341
  jbDirectory(),
341
342
  FEE_PROJECT_ID,
342
343
  SUCKER_REGISTRY,
343
- address(LOANS_CONTRACT)
344
+ address(LOANS_CONTRACT),
345
+ address(0)
344
346
  );
345
347
 
346
348
  REV_DEPLOYER = new REVDeployer{salt: REV_DEPLOYER_SALT}(
@@ -428,7 +430,8 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
428
430
  REVLoanSource memory sauce = REVLoanSource({token: address(TOKEN), terminal: jbMultiTerminal()});
429
431
 
430
432
  vm.prank(USER);
431
- (uint256 newLoanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable, tokens, payable(USER), prepaidFee);
433
+ (uint256 newLoanId,) =
434
+ LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable, tokens, payable(USER), prepaidFee, USER);
432
435
 
433
436
  REVLoan memory loan = LOANS_CONTRACT.loanOf(newLoanId);
434
437
  assertEq(loan.amount, loanable);
@@ -480,7 +483,8 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
480
483
  REVLoanSource memory sauce = REVLoanSource({token: address(TOKEN), terminal: jbMultiTerminal()});
481
484
 
482
485
  vm.prank(USER);
483
- (uint256 newLoanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable, tokens, payable(USER), prepaidFee);
486
+ (uint256 newLoanId,) =
487
+ LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable, tokens, payable(USER), prepaidFee, USER);
484
488
 
485
489
  REVLoan memory loan = LOANS_CONTRACT.loanOf(newLoanId);
486
490
  assertEq(loan.amount, loanable);
@@ -539,7 +543,8 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
539
543
  uint256 balanceBeforeLoan = TOKEN.balanceOf(USER);
540
544
 
541
545
  // Create the new loan.
542
- (uint256 newLoanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, loanable, tokens, payable(USER), prepaidFee);
546
+ (uint256 newLoanId,) =
547
+ LOANS_CONTRACT.borrowFrom(REVNET_ID, source, loanable, tokens, payable(USER), prepaidFee, USER);
543
548
  REVLoan memory loan = LOANS_CONTRACT.loanOf(newLoanId);
544
549
 
545
550
  // Check what amount we actually received.
@@ -610,7 +615,8 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
610
615
  REVLoanSource memory sauce = REVLoanSource({token: address(TOKEN), terminal: jbMultiTerminal()});
611
616
 
612
617
  vm.prank(USER);
613
- (uint256 newLoanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable, tokens, payable(USER), prepaidFee);
618
+ (uint256 newLoanId,) =
619
+ LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable, tokens, payable(USER), prepaidFee, USER);
614
620
 
615
621
  REVLoan memory loan = LOANS_CONTRACT.loanOf(newLoanId);
616
622
  assertEq(loan.amount, loanable);
@@ -815,7 +821,7 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
815
821
  uint256 balanceBefore = USER.balance;
816
822
 
817
823
  vm.prank(USER);
818
- (uint256 newLoanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable, tokens, payable(USER), 500);
824
+ (uint256 newLoanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable, tokens, payable(USER), 500, USER);
819
825
 
820
826
  REVLoan memory loan = LOANS_CONTRACT.loanOf(newLoanId);
821
827
  assertEq(loan.amount, loanable);
@@ -869,7 +875,7 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
869
875
 
870
876
  vm.prank(USER);
871
877
  (newLoanId,) =
872
- LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable, tokens, payable(USER), prepaidFeePercent);
878
+ LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable, tokens, payable(USER), prepaidFeePercent, USER);
873
879
  }
874
880
 
875
881
  REVLoan memory loan = LOANS_CONTRACT.loanOf(newLoanId);
@@ -976,7 +982,7 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
976
982
  REVLoanSource memory sauce = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: jbMultiTerminal()});
977
983
 
978
984
  vm.prank(USER);
979
- (uint256 newLoanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable, tokens, payable(USER), 500);
985
+ (uint256 newLoanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable, tokens, payable(USER), 500, USER);
980
986
 
981
987
  REVLoan memory loan = LOANS_CONTRACT.loanOf(newLoanId);
982
988
 
@@ -1058,7 +1064,7 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
1058
1064
  REVLoanSource memory sauce = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: jbMultiTerminal()});
1059
1065
 
1060
1066
  vm.prank(USER);
1061
- (uint256 newLoanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable, tokens, payable(USER), 500);
1067
+ (uint256 newLoanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable, tokens, payable(USER), 500, USER);
1062
1068
 
1063
1069
  REVLoan memory loan = LOANS_CONTRACT.loanOf(newLoanId);
1064
1070
 
@@ -1121,7 +1127,7 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
1121
1127
  REVLoanSource memory sauce = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: jbMultiTerminal()});
1122
1128
 
1123
1129
  vm.prank(USER);
1124
- (uint256 newLoanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable, tokens, payable(USER), 500);
1130
+ (uint256 newLoanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable, tokens, payable(USER), 500, USER);
1125
1131
 
1126
1132
  REVLoan memory loan = LOANS_CONTRACT.loanOf(newLoanId);
1127
1133
 
@@ -1151,7 +1157,15 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
1151
1157
  );
1152
1158
 
1153
1159
  address unauthorized = address(1);
1154
- vm.expectRevert(abi.encodeWithSelector(REVLoans.REVLoans_Unauthorized.selector, unauthorized, USER));
1160
+ vm.expectRevert(
1161
+ abi.encodeWithSelector(
1162
+ JBPermissioned.JBPermissioned_Unauthorized.selector,
1163
+ USER,
1164
+ unauthorized,
1165
+ REVNET_ID,
1166
+ JBPermissionIds.REALLOCATE_LOAN
1167
+ )
1168
+ );
1155
1169
 
1156
1170
  vm.prank(unauthorized);
1157
1171
  LOANS_CONTRACT.reallocateCollateralFromLoan(
@@ -1251,7 +1265,8 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
1251
1265
  revnetProjectId, JBConstants.NATIVE_TOKEN, paymentPerBorrow, USER, 0, "", ""
1252
1266
  );
1253
1267
 
1254
- (, REVLoan memory loan) = LOANS_CONTRACT.borrowFrom(revnetProjectId, source, 0, tokens, payable(USER), 500);
1268
+ (, REVLoan memory loan) =
1269
+ LOANS_CONTRACT.borrowFrom(revnetProjectId, source, 0, tokens, payable(USER), 500, USER);
1255
1270
 
1256
1271
  if (i == 0) {
1257
1272
  initialBorrow = loan.amount;
@@ -1336,7 +1351,7 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
1336
1351
  uint256 balanceBefore = USER.balance;
1337
1352
  REVLoanSource memory source = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: jbMultiTerminal()});
1338
1353
  (uint256 newLoanId, REVLoan memory loan) =
1339
- LOANS_CONTRACT.borrowFrom(revnetProjectId, source, loanable, tokens, payable(USER), 500);
1354
+ LOANS_CONTRACT.borrowFrom(revnetProjectId, source, loanable, tokens, payable(USER), 500, USER);
1340
1355
 
1341
1356
  // Ensure loans contract isn't hodling
1342
1357
  assertEq(address(LOANS_CONTRACT).balance, 0);
@@ -1395,7 +1410,7 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
1395
1410
  REVLoanSource memory sauce = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: jbMultiTerminal()});
1396
1411
 
1397
1412
  vm.prank(USER);
1398
- (uint256 newLoanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable, tokens, payable(USER), 500);
1413
+ (uint256 newLoanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable, tokens, payable(USER), 500, USER);
1399
1414
 
1400
1415
  REVLoan memory loan = LOANS_CONTRACT.loanOf(newLoanId);
1401
1416
 
@@ -1480,7 +1495,7 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
1480
1495
  REVLoanSource memory sauce = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: jbMultiTerminal()});
1481
1496
 
1482
1497
  vm.prank(USER);
1483
- (uint256 newLoanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable, tokens, payable(USER), 500);
1498
+ (uint256 newLoanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable, tokens, payable(USER), 500, USER);
1484
1499
 
1485
1500
  REVLoan memory loan = LOANS_CONTRACT.loanOf(newLoanId);
1486
1501
 
@@ -1553,7 +1568,8 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
1553
1568
  assertEq(sources.length, 0);
1554
1569
 
1555
1570
  vm.prank(USER);
1556
- (, REVLoan memory loan) = LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable, tokens, payable(USER), 100);
1571
+ (, REVLoan memory loan) =
1572
+ LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable, tokens, payable(USER), 100, USER);
1557
1573
 
1558
1574
  // Source should exist after a borrow
1559
1575
  REVLoanSource[] memory sourcesUpdated = LOANS_CONTRACT.loanSourcesOf(REVNET_ID);
@@ -1596,7 +1612,7 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
1596
1612
  vm.expectRevert(
1597
1613
  abi.encodeWithSelector(REVLoans.REVLoans_InvalidPrepaidFeePercent.selector, feePercentage, 25, 500)
1598
1614
  );
1599
- LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, 1, tokens, payable(USER), feePercentage);
1615
+ LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, 1, tokens, payable(USER), feePercentage, USER);
1600
1616
  }
1601
1617
 
1602
1618
  function test_liquidateLoans() external {
@@ -1618,7 +1634,7 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
1618
1634
 
1619
1635
  vm.prank(USER);
1620
1636
  (uint256 loanId, REVLoan memory loan) =
1621
- LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable, tokens, payable(USER), 100);
1637
+ LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable, tokens, payable(USER), 100, USER);
1622
1638
 
1623
1639
  // Take out another loan
1624
1640
  vm.prank(USER);
@@ -1636,7 +1652,7 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
1636
1652
 
1637
1653
  vm.prank(USER);
1638
1654
  (uint256 loanId2, REVLoan memory loan2) =
1639
- LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable2, tokens2, payable(USER), 50);
1655
+ LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable2, tokens2, payable(USER), 50, USER);
1640
1656
 
1641
1657
  // Warp further than the loan liquidation duration.
1642
1658
  vm.warp(block.timestamp + 10_000 days);
@@ -1674,7 +1690,7 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
1674
1690
 
1675
1691
  vm.prank(USER);
1676
1692
  (uint256 loanId, REVLoan memory loan) =
1677
- LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable, tokens, payable(USER), 100);
1693
+ LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable, tokens, payable(USER), 100, USER);
1678
1694
 
1679
1695
  // Attempt to liquidate before the loan is expired and loop will break
1680
1696
  LOANS_CONTRACT.liquidateExpiredLoansFrom(REVNET_ID, 0, 2);
@@ -1747,14 +1763,22 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
1747
1763
  REVLoanSource memory sauce = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: jbMultiTerminal()});
1748
1764
 
1749
1765
  vm.prank(USER);
1750
- (uint256 loanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable, tokens, payable(USER), 100);
1766
+ (uint256 loanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable, tokens, payable(USER), 100, USER);
1751
1767
 
1752
1768
  // empty allowance data
1753
1769
  JBSingleAllowance memory allowance;
1754
1770
 
1755
1771
  // call to pay-down the loan
1756
1772
  /* vm.prank(USER); */
1757
- vm.expectRevert(abi.encodeWithSelector(REVLoans.REVLoans_Unauthorized.selector, address(this), USER));
1773
+ vm.expectRevert(
1774
+ abi.encodeWithSelector(
1775
+ JBPermissioned.JBPermissioned_Unauthorized.selector,
1776
+ USER,
1777
+ address(this),
1778
+ REVNET_ID,
1779
+ JBPermissionIds.REPAY_LOAN
1780
+ )
1781
+ );
1758
1782
  LOANS_CONTRACT.repayLoan{value: 0}(loanId, 0, 0, payable(USER), allowance);
1759
1783
  }
1760
1784
 
@@ -1777,7 +1801,7 @@ contract REVLoansSourcedTests is TestBaseWorkflow {
1777
1801
 
1778
1802
  vm.prank(USER);
1779
1803
  (uint256 loanId, REVLoan memory loan) =
1780
- LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable, tokens, payable(USER), 100);
1804
+ LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable, tokens, payable(USER), 100, USER);
1781
1805
 
1782
1806
  // empty allowance data
1783
1807
  JBSingleAllowance memory allowance;
@@ -304,7 +304,6 @@ contract REVLoansUnsourcedTests is TestBaseWorkflow {
304
304
 
305
305
  LOANS_CONTRACT = new REVLoans({
306
306
  controller: jbController(),
307
- projects: jbProjects(),
308
307
  revId: FEE_PROJECT_ID,
309
308
  owner: address(this),
310
309
  permit2: permit2(),
@@ -316,7 +315,8 @@ contract REVLoansUnsourcedTests is TestBaseWorkflow {
316
315
  jbDirectory(),
317
316
  FEE_PROJECT_ID,
318
317
  SUCKER_REGISTRY,
319
- address(LOANS_CONTRACT)
318
+ address(LOANS_CONTRACT),
319
+ address(0)
320
320
  );
321
321
 
322
322
  REV_DEPLOYER = new REVDeployer{salt: REV_DEPLOYER_SALT}(
@@ -393,6 +393,6 @@ contract REVLoansUnsourcedTests is TestBaseWorkflow {
393
393
  REVLoanSource memory sauce = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: jbMultiTerminal()});
394
394
 
395
395
  vm.prank(USER);
396
- LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable, tokens, payable(USER), 500);
396
+ LOANS_CONTRACT.borrowFrom(REVNET_ID, sauce, loanable, tokens, payable(USER), 500, USER);
397
397
  }
398
398
  }
@@ -207,7 +207,6 @@ contract TestBurnHeldTokens is TestBaseWorkflow {
207
207
 
208
208
  LOANS_CONTRACT = new REVLoans({
209
209
  controller: jbController(),
210
- projects: jbProjects(),
211
210
  revId: FEE_PROJECT_ID,
212
211
  owner: address(this),
213
212
  permit2: permit2(),
@@ -219,7 +218,8 @@ contract TestBurnHeldTokens is TestBaseWorkflow {
219
218
  jbDirectory(),
220
219
  FEE_PROJECT_ID,
221
220
  SUCKER_REGISTRY,
222
- address(LOANS_CONTRACT)
221
+ address(LOANS_CONTRACT),
222
+ address(0)
223
223
  );
224
224
 
225
225
  REV_DEPLOYER = new REVDeployer{salt: REV_DEPLOYER_SALT}(
@@ -136,7 +136,6 @@ contract TestCEIPattern is TestBaseWorkflow {
136
136
  .addPriceFeedFor(0, uint32(uint160(address(TOKEN))), uint32(uint160(JBConstants.NATIVE_TOKEN)), priceFeed);
137
137
  LOANS_CONTRACT = new REVLoans({
138
138
  controller: jbController(),
139
- projects: jbProjects(),
140
139
  revId: FEE_PROJECT_ID,
141
140
  owner: address(this),
142
141
  permit2: permit2(),
@@ -147,7 +146,8 @@ contract TestCEIPattern is TestBaseWorkflow {
147
146
  jbDirectory(),
148
147
  FEE_PROJECT_ID,
149
148
  SUCKER_REGISTRY,
150
- address(LOANS_CONTRACT)
149
+ address(LOANS_CONTRACT),
150
+ address(0)
151
151
  );
152
152
 
153
153
  REV_DEPLOYER = new REVDeployer{salt: REV_DEPLOYER_SALT}(
@@ -283,7 +283,7 @@ contract TestCEIPattern is TestBaseWorkflow {
283
283
  );
284
284
  REVLoanSource memory source = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: jbMultiTerminal()});
285
285
  vm.prank(user);
286
- (loanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(user), prepaidFee);
286
+ (loanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(user), prepaidFee, user);
287
287
  }
288
288
 
289
289
  /// @notice After borrowing, loan.amount and loan.collateral are set correctly (CEI: state written before external
@@ -347,7 +347,7 @@ contract TestCEIPattern is TestBaseWorkflow {
347
347
  );
348
348
  REVLoanSource memory source = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: jbMultiTerminal()});
349
349
  vm.prank(USER);
350
- LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens2, payable(USER), 25);
350
+ LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens2, payable(USER), 25, USER);
351
351
  }
352
352
 
353
353
  // Total collateral should equal sum of both loans' collateral
@@ -389,7 +389,8 @@ contract TestCEIPattern is TestBaseWorkflow {
389
389
 
390
390
  // Borrow with attacker as beneficiary — attacker's receive() will fire when ETH arrives.
391
391
  vm.prank(address(attacker));
392
- (uint256 loanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens, payable(address(attacker)), 25);
392
+ (uint256 loanId,) =
393
+ LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens, payable(address(attacker)), 25, address(attacker));
393
394
 
394
395
  assertEq(loanId, expectedLoanId, "LoanId should match pre-computed value");
395
396
 
@@ -472,7 +473,7 @@ contract TestCEIPattern is TestBaseWorkflow {
472
473
  REVLoanSource memory source = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: jbMultiTerminal()});
473
474
 
474
475
  vm.prank(USER);
475
- (uint256 loanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens, payable(USER), 25);
476
+ (uint256 loanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens, payable(USER), 25, USER);
476
477
 
477
478
  REVLoan memory loan = LOANS_CONTRACT.loanOf(loanId);
478
479
 
@@ -220,7 +220,6 @@ contract TestCashOutCallerValidation is TestBaseWorkflow {
220
220
 
221
221
  LOANS_CONTRACT = new REVLoans({
222
222
  controller: jbController(),
223
- projects: jbProjects(),
224
223
  revId: FEE_PROJECT_ID,
225
224
  owner: address(this),
226
225
  permit2: permit2(),
@@ -232,7 +231,8 @@ contract TestCashOutCallerValidation is TestBaseWorkflow {
232
231
  jbDirectory(),
233
232
  FEE_PROJECT_ID,
234
233
  SUCKER_REGISTRY,
235
- address(LOANS_CONTRACT)
234
+ address(LOANS_CONTRACT),
235
+ address(0)
236
236
  );
237
237
 
238
238
  REV_DEPLOYER = new REVDeployer{salt: REV_DEPLOYER_SALT}(
@@ -150,7 +150,6 @@ contract TestConversionDocumentation is TestBaseWorkflow {
150
150
 
151
151
  LOANS_CONTRACT = new REVLoans({
152
152
  controller: jbController(),
153
- projects: jbProjects(),
154
153
  revId: FEE_PROJECT_ID,
155
154
  owner: address(this),
156
155
  permit2: permit2(),
@@ -162,7 +161,8 @@ contract TestConversionDocumentation is TestBaseWorkflow {
162
161
  jbDirectory(),
163
162
  FEE_PROJECT_ID,
164
163
  SUCKER_REGISTRY,
165
- address(LOANS_CONTRACT)
164
+ address(LOANS_CONTRACT),
165
+ address(0)
166
166
  );
167
167
 
168
168
  REV_DEPLOYER = new REVDeployer{salt: REV_DEPLOYER_SALT}(
@@ -101,7 +101,6 @@ contract TestCrossCurrencyReclaim is TestBaseWorkflow {
101
101
 
102
102
  LOANS_CONTRACT = new REVLoans({
103
103
  controller: jbController(),
104
- projects: jbProjects(),
105
104
  revId: FEE_PROJECT_ID,
106
105
  owner: address(this),
107
106
  permit2: permit2(),
@@ -113,7 +112,8 @@ contract TestCrossCurrencyReclaim is TestBaseWorkflow {
113
112
  jbDirectory(),
114
113
  FEE_PROJECT_ID,
115
114
  SUCKER_REGISTRY,
116
- address(LOANS_CONTRACT)
115
+ address(LOANS_CONTRACT),
116
+ address(0)
117
117
  );
118
118
 
119
119
  REV_DEPLOYER = new REVDeployer{salt: REV_DEPLOYER_SALT}(
@@ -99,7 +99,6 @@ contract TestCrossSourceReallocation is TestBaseWorkflow {
99
99
  .addPriceFeedFor(0, uint32(uint160(address(TOKEN))), uint32(uint160(JBConstants.NATIVE_TOKEN)), priceFeed);
100
100
  LOANS_CONTRACT = new REVLoans({
101
101
  controller: jbController(),
102
- projects: jbProjects(),
103
102
  revId: FEE_PROJECT_ID,
104
103
  owner: address(this),
105
104
  permit2: permit2(),
@@ -110,7 +109,8 @@ contract TestCrossSourceReallocation is TestBaseWorkflow {
110
109
  jbDirectory(),
111
110
  FEE_PROJECT_ID,
112
111
  SUCKER_REGISTRY,
113
- address(LOANS_CONTRACT)
112
+ address(LOANS_CONTRACT),
113
+ address(0)
114
114
  );
115
115
 
116
116
  REV_DEPLOYER = new REVDeployer{salt: REV_DEPLOYER_SALT}(
@@ -246,7 +246,7 @@ contract TestCrossSourceReallocation is TestBaseWorkflow {
246
246
  );
247
247
  REVLoanSource memory source = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: jbMultiTerminal()});
248
248
  vm.prank(user);
249
- (loanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(user), prepaidFee);
249
+ (loanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(user), prepaidFee, user);
250
250
  }
251
251
 
252
252
  /// @notice Reallocating with the same source (token + terminal) should succeed.
@@ -291,7 +291,6 @@ contract TestERC2771MetaTx is TestBaseWorkflow {
291
291
  // Deploy LOANS_CONTRACT with the forwarder as trusted forwarder.
292
292
  LOANS_CONTRACT = new REVLoans({
293
293
  controller: jbController(),
294
- projects: jbProjects(),
295
294
  revId: FEE_PROJECT_ID,
296
295
  owner: address(this),
297
296
  permit2: permit2(),
@@ -303,7 +302,8 @@ contract TestERC2771MetaTx is TestBaseWorkflow {
303
302
  jbDirectory(),
304
303
  FEE_PROJECT_ID,
305
304
  SUCKER_REGISTRY,
306
- address(LOANS_CONTRACT)
305
+ address(LOANS_CONTRACT),
306
+ address(0)
307
307
  );
308
308
 
309
309
  REV_DEPLOYER = new REVDeployer{salt: REV_DEPLOYER_SALT}(
@@ -400,7 +400,8 @@ contract TestERC2771MetaTx is TestBaseWorkflow {
400
400
  0, // minBorrowAmount
401
401
  tokenCount,
402
402
  payable(signerAddr),
403
- uint256(25) // MIN_PREPAID_FEE_PERCENT
403
+ uint256(25), // MIN_PREPAID_FEE_PERCENT
404
+ signerAddr // holder
404
405
  );
405
406
 
406
407
  // Build the forwarded request signed by the signer.
@@ -448,7 +449,8 @@ contract TestERC2771MetaTx is TestBaseWorkflow {
448
449
  REVLoanSource memory source = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: jbMultiTerminal()});
449
450
 
450
451
  vm.prank(signerAddr);
451
- (uint256 loanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(signerAddr), 25);
452
+ (uint256 loanId,) =
453
+ LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(signerAddr), 25, signerAddr);
452
454
 
453
455
  REVLoan memory loan = LOANS_CONTRACT.loanOf(loanId);
454
456
  assertTrue(loan.amount > 0, "Loan should exist");
@@ -90,7 +90,6 @@ contract TestEmptyBuybackSpecs is TestBaseWorkflow {
90
90
  MOCK_BUYBACK_MINT_PATH = new MockBuybackDataHookMintPath();
91
91
  LOANS_CONTRACT = new REVLoans({
92
92
  controller: jbController(),
93
- projects: jbProjects(),
94
93
  revId: FEE_PROJECT_ID,
95
94
  owner: address(this),
96
95
  permit2: permit2(),
@@ -101,7 +100,8 @@ contract TestEmptyBuybackSpecs is TestBaseWorkflow {
101
100
  jbDirectory(),
102
101
  FEE_PROJECT_ID,
103
102
  SUCKER_REGISTRY,
104
- address(LOANS_CONTRACT)
103
+ address(LOANS_CONTRACT),
104
+ address(0)
105
105
  );
106
106
 
107
107
  REV_DEPLOYER = new REVDeployer{salt: REV_DEPLOYER_SALT}(
@@ -102,7 +102,6 @@ contract TestFlashLoanSurplus is TestBaseWorkflow {
102
102
  .addPriceFeedFor(0, uint32(uint160(address(TOKEN))), uint32(uint160(JBConstants.NATIVE_TOKEN)), priceFeed);
103
103
  LOANS_CONTRACT = new REVLoans({
104
104
  controller: jbController(),
105
- projects: jbProjects(),
106
105
  revId: FEE_PROJECT_ID,
107
106
  owner: address(this),
108
107
  permit2: permit2(),
@@ -113,7 +112,8 @@ contract TestFlashLoanSurplus is TestBaseWorkflow {
113
112
  jbDirectory(),
114
113
  FEE_PROJECT_ID,
115
114
  SUCKER_REGISTRY,
116
- address(LOANS_CONTRACT)
115
+ address(LOANS_CONTRACT),
116
+ address(0)
117
117
  );
118
118
 
119
119
  REV_DEPLOYER = new REVDeployer{salt: REV_DEPLOYER_SALT}(
@@ -250,7 +250,7 @@ contract TestFlashLoanSurplus is TestBaseWorkflow {
250
250
  );
251
251
  REVLoanSource memory source = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: jbMultiTerminal()});
252
252
  vm.prank(user);
253
- (loanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(user), prepaidFee);
253
+ (loanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(user), prepaidFee, user);
254
254
  }
255
255
 
256
256
  /// @notice Donate ETH via addToBalanceOf, then borrow. The donation costs more than the extra borrowable amount.