@rev-net/core-v6 0.0.29 → 0.0.31
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.
- package/ADMINISTRATION.md +19 -9
- package/ARCHITECTURE.md +3 -0
- package/AUDIT_INSTRUCTIONS.md +11 -1
- package/CHANGELOG.md +26 -0
- package/README.md +1 -0
- package/RISKS.md +28 -4
- package/SKILLS.md +2 -1
- package/USER_JOURNEYS.md +28 -3
- package/package.json +8 -8
- package/references/operations.md +1 -1
- package/script/Deploy.s.sol +26 -4
- package/src/REVDeployer.sol +4 -2
- package/src/REVHiddenTokens.sol +149 -0
- package/src/REVLoans.sol +192 -199
- package/src/REVOwner.sol +51 -14
- package/src/interfaces/IREVHiddenTokens.sol +53 -0
- package/src/interfaces/IREVLoans.sol +8 -6
- package/test/REV.integrations.t.sol +12 -2
- package/test/REVAutoIssuanceFuzz.t.sol +12 -2
- package/test/REVDeployerRegressions.t.sol +14 -3
- package/test/REVInvincibility.t.sol +27 -8
- package/test/REVInvincibilityHandler.sol +1 -1
- package/test/REVLifecycle.t.sol +14 -3
- package/test/REVLoans.invariants.t.sol +15 -4
- package/test/REVLoansAttacks.t.sol +19 -7
- package/test/REVLoansFeeRecovery.t.sol +24 -13
- package/test/REVLoansFindings.t.sol +16 -5
- package/test/REVLoansRegressions.t.sol +15 -4
- package/test/REVLoansSourceFeeRecovery.t.sol +16 -5
- package/test/REVLoansSourced.t.sol +60 -25
- package/test/REVLoansUnSourced.t.sol +15 -4
- package/test/TestBurnHeldTokens.t.sol +14 -3
- package/test/TestCEIPattern.t.sol +19 -7
- package/test/TestCashOutCallerValidation.t.sol +15 -4
- package/test/TestConversionDocumentation.t.sol +14 -3
- package/test/TestCrossCurrencyReclaim.t.sol +14 -3
- package/test/TestCrossSourceReallocation.t.sol +15 -4
- package/test/TestERC2771MetaTx.t.sol +18 -5
- package/test/TestEmptyBuybackSpecs.t.sol +14 -3
- package/test/TestFlashLoanSurplus.t.sol +15 -4
- package/test/TestHiddenTokens.t.sol +431 -0
- package/test/TestHookArrayOOB.t.sol +14 -3
- package/test/TestLiquidationBehavior.t.sol +16 -5
- package/test/TestLoanSourceRotation.t.sol +20 -7
- package/test/TestLoansCashOutDelay.t.sol +18 -7
- package/test/TestLongTailEconomics.t.sol +14 -3
- package/test/TestLowFindings.t.sol +25 -9
- package/test/TestMixedFixes.t.sol +19 -8
- package/test/TestPermit2Signatures.t.sol +15 -4
- package/test/TestReallocationSandwich.t.sol +16 -4
- package/test/TestRevnetRegressions.t.sol +16 -5
- package/test/TestSplitWeightAdjustment.t.sol +16 -4
- package/test/TestSplitWeightE2E.t.sol +18 -4
- package/test/TestSplitWeightFork.t.sol +16 -3
- package/test/TestStageTransitionBorrowable.t.sol +14 -3
- package/test/TestSwapTerminalPermission.t.sol +14 -3
- package/test/TestUint112Overflow.t.sol +15 -4
- package/test/TestZeroAmountLoanGuard.t.sol +15 -4
- package/test/TestZeroRepayment.t.sol +15 -4
- package/test/audit/CodexPhantomSurplusTerminal.t.sol +367 -0
- package/test/audit/LoanIdOverflowGuard.t.sol +16 -5
- package/test/audit/NemesisOperatorDelegation.t.sol +289 -0
- package/test/fork/ForkTestBase.sol +18 -4
- package/test/fork/TestLoanBorrowFork.t.sol +2 -1
- package/test/fork/TestLoanERC20Fork.t.sol +4 -2
- package/test/fork/TestLoanTransferFork.t.sol +12 -2
- package/test/helpers/MaliciousContracts.sol +1 -1
- package/test/mock/MockBuybackCashOutRecorder.sol +2 -0
- package/test/mock/MockBuybackDataHook.sol +3 -1
- package/test/mock/MockBuybackDataHookMintPath.sol +2 -0
- package/test/mock/MockSuckerRegistry.sol +17 -0
- package/test/regression/TestBurnPermissionRequired.t.sol +16 -5
- package/test/regression/TestCashOutBuybackFeeLeak.t.sol +16 -3
- package/test/regression/TestCrossRevnetLiquidation.t.sol +14 -3
- package/test/regression/TestCumulativeLoanCounter.t.sol +15 -4
- package/test/regression/TestLiquidateGapHandling.t.sol +15 -4
- package/test/regression/TestZeroPriceFeed.t.sol +17 -6
|
@@ -38,6 +38,8 @@ import {JBSuckerRegistry} from "@bananapus/suckers-v6/src/JBSuckerRegistry.sol";
|
|
|
38
38
|
import {JB721TiersHookDeployer} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
|
|
39
39
|
import {JB721TiersHook} from "@bananapus/721-hook-v6/src/JB721TiersHook.sol";
|
|
40
40
|
import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
|
|
41
|
+
import {JB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/JB721CheckpointsDeployer.sol";
|
|
42
|
+
import {IJB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/interfaces/IJB721CheckpointsDeployer.sol";
|
|
41
43
|
import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
|
|
42
44
|
import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
|
|
43
45
|
import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
|
|
@@ -46,6 +48,7 @@ import {JBRuleset} from "@bananapus/core-v6/src/structs/JBRuleset.sol";
|
|
|
46
48
|
import {JBPayHookSpecification} from "@bananapus/core-v6/src/structs/JBPayHookSpecification.sol";
|
|
47
49
|
import {REVOwner} from "../src/REVOwner.sol";
|
|
48
50
|
import {IREVDeployer} from "../src/interfaces/IREVDeployer.sol";
|
|
51
|
+
import {MockSuckerRegistry} from "./mock/MockSuckerRegistry.sol";
|
|
49
52
|
|
|
50
53
|
/// @notice A malicious terminal that re-enters REVLoans during fee payment in _adjust().
|
|
51
54
|
/// @dev Reentrancy during pay() callback in _adjust.
|
|
@@ -98,7 +101,8 @@ contract ReentrantTerminal is ERC165, IJBPayoutTerminal {
|
|
|
98
101
|
0, // minBorrowAmount
|
|
99
102
|
reenterCollateral,
|
|
100
103
|
payable(address(this)),
|
|
101
|
-
25 // MIN_PREPAID_FEE_PERCENT
|
|
104
|
+
25, // MIN_PREPAID_FEE_PERCENT
|
|
105
|
+
address(this)
|
|
102
106
|
) {}
|
|
103
107
|
catch {
|
|
104
108
|
// Expected to revert if reentrancy guard exists
|
|
@@ -368,7 +372,14 @@ contract REVLoansAttacks is TestBaseWorkflow {
|
|
|
368
372
|
SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
|
|
369
373
|
HOOK_STORE = new JB721TiersHookStore();
|
|
370
374
|
EXAMPLE_HOOK = new JB721TiersHook(
|
|
371
|
-
jbDirectory(),
|
|
375
|
+
jbDirectory(),
|
|
376
|
+
jbPermissions(),
|
|
377
|
+
jbPrices(),
|
|
378
|
+
jbRulesets(),
|
|
379
|
+
HOOK_STORE,
|
|
380
|
+
jbSplits(),
|
|
381
|
+
IJB721CheckpointsDeployer(address(new JB721CheckpointsDeployer())),
|
|
382
|
+
multisig()
|
|
372
383
|
);
|
|
373
384
|
ADDRESS_REGISTRY = new JBAddressRegistry();
|
|
374
385
|
HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
|
|
@@ -383,7 +394,7 @@ contract REVLoansAttacks is TestBaseWorkflow {
|
|
|
383
394
|
|
|
384
395
|
LOANS_CONTRACT = new REVLoans({
|
|
385
396
|
controller: jbController(),
|
|
386
|
-
|
|
397
|
+
suckerRegistry: IJBSuckerRegistry(address(new MockSuckerRegistry())),
|
|
387
398
|
revId: FEE_PROJECT_ID,
|
|
388
399
|
owner: address(this),
|
|
389
400
|
permit2: permit2(),
|
|
@@ -395,7 +406,8 @@ contract REVLoansAttacks is TestBaseWorkflow {
|
|
|
395
406
|
jbDirectory(),
|
|
396
407
|
FEE_PROJECT_ID,
|
|
397
408
|
SUCKER_REGISTRY,
|
|
398
|
-
address(LOANS_CONTRACT)
|
|
409
|
+
address(LOANS_CONTRACT),
|
|
410
|
+
address(0)
|
|
399
411
|
);
|
|
400
412
|
|
|
401
413
|
REV_DEPLOYER = new REVDeployer{salt: REV_DEPLOYER_SALT}(
|
|
@@ -474,7 +486,7 @@ contract REVLoansAttacks is TestBaseWorkflow {
|
|
|
474
486
|
REVLoanSource memory source = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: jbMultiTerminal()});
|
|
475
487
|
|
|
476
488
|
vm.prank(user);
|
|
477
|
-
(loanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(user), prepaidFee);
|
|
489
|
+
(loanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(user), prepaidFee, user);
|
|
478
490
|
}
|
|
479
491
|
|
|
480
492
|
// =========================================================================
|
|
@@ -646,7 +658,7 @@ contract REVLoansAttacks is TestBaseWorkflow {
|
|
|
646
658
|
vm.assume(borrowable > 0);
|
|
647
659
|
|
|
648
660
|
vm.prank(userA);
|
|
649
|
-
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokensA, payable(userA), 25);
|
|
661
|
+
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokensA, payable(userA), 25, userA);
|
|
650
662
|
|
|
651
663
|
// After borrowing, tokensA are burned as collateral
|
|
652
664
|
// But the surplus is adjusted by adding totalBorrowed
|
|
@@ -771,7 +783,7 @@ contract REVLoansAttacks is TestBaseWorkflow {
|
|
|
771
783
|
|
|
772
784
|
// Borrow with max prepaid fee (so no additional fee on immediate repay)
|
|
773
785
|
vm.prank(USER);
|
|
774
|
-
(uint256 loanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens, payable(USER), 500);
|
|
786
|
+
(uint256 loanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens, payable(USER), 500, USER);
|
|
775
787
|
|
|
776
788
|
REVLoan memory loan = LOANS_CONTRACT.loanOf(loanId);
|
|
777
789
|
|
|
@@ -39,6 +39,8 @@ import {JBSuckerRegistry} from "@bananapus/suckers-v6/src/JBSuckerRegistry.sol";
|
|
|
39
39
|
import {JB721TiersHookDeployer} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
|
|
40
40
|
import {JB721TiersHook} from "@bananapus/721-hook-v6/src/JB721TiersHook.sol";
|
|
41
41
|
import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
|
|
42
|
+
import {JB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/JB721CheckpointsDeployer.sol";
|
|
43
|
+
import {IJB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/interfaces/IJB721CheckpointsDeployer.sol";
|
|
42
44
|
import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
|
|
43
45
|
import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
|
|
44
46
|
import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
|
|
@@ -47,6 +49,7 @@ import {JBPayHookSpecification} from "@bananapus/core-v6/src/structs/JBPayHookSp
|
|
|
47
49
|
import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
|
|
48
50
|
import {REVOwner} from "../src/REVOwner.sol";
|
|
49
51
|
import {IREVDeployer} from "../src/interfaces/IREVDeployer.sol";
|
|
52
|
+
import {MockSuckerRegistry} from "./mock/MockSuckerRegistry.sol";
|
|
50
53
|
|
|
51
54
|
/// @notice A terminal mock that always reverts on pay(), used to simulate fee payment failure.
|
|
52
55
|
contract RevertingFeeTerminal is ERC165, IJBPayoutTerminal {
|
|
@@ -333,7 +336,14 @@ contract REVLoansFeeRecovery is TestBaseWorkflow {
|
|
|
333
336
|
SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
|
|
334
337
|
HOOK_STORE = new JB721TiersHookStore();
|
|
335
338
|
EXAMPLE_HOOK = new JB721TiersHook(
|
|
336
|
-
jbDirectory(),
|
|
339
|
+
jbDirectory(),
|
|
340
|
+
jbPermissions(),
|
|
341
|
+
jbPrices(),
|
|
342
|
+
jbRulesets(),
|
|
343
|
+
HOOK_STORE,
|
|
344
|
+
jbSplits(),
|
|
345
|
+
IJB721CheckpointsDeployer(address(new JB721CheckpointsDeployer())),
|
|
346
|
+
multisig()
|
|
337
347
|
);
|
|
338
348
|
ADDRESS_REGISTRY = new JBAddressRegistry();
|
|
339
349
|
HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
|
|
@@ -349,7 +359,7 @@ contract REVLoansFeeRecovery is TestBaseWorkflow {
|
|
|
349
359
|
|
|
350
360
|
LOANS_CONTRACT = new REVLoans({
|
|
351
361
|
controller: jbController(),
|
|
352
|
-
|
|
362
|
+
suckerRegistry: IJBSuckerRegistry(address(new MockSuckerRegistry())),
|
|
353
363
|
revId: FEE_PROJECT_ID,
|
|
354
364
|
owner: address(this),
|
|
355
365
|
permit2: permit2(),
|
|
@@ -361,7 +371,8 @@ contract REVLoansFeeRecovery is TestBaseWorkflow {
|
|
|
361
371
|
jbDirectory(),
|
|
362
372
|
FEE_PROJECT_ID,
|
|
363
373
|
SUCKER_REGISTRY,
|
|
364
|
-
address(LOANS_CONTRACT)
|
|
374
|
+
address(LOANS_CONTRACT),
|
|
375
|
+
address(0)
|
|
365
376
|
);
|
|
366
377
|
|
|
367
378
|
REV_DEPLOYER = new REVDeployer{salt: REV_DEPLOYER_SALT}(
|
|
@@ -450,7 +461,7 @@ contract REVLoansFeeRecovery is TestBaseWorkflow {
|
|
|
450
461
|
borrowerBalanceBefore = user.balance;
|
|
451
462
|
|
|
452
463
|
vm.prank(user);
|
|
453
|
-
(loanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(user), prepaidFee);
|
|
464
|
+
(loanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(user), prepaidFee, user);
|
|
454
465
|
|
|
455
466
|
borrowerBalanceAfter = user.balance;
|
|
456
467
|
}
|
|
@@ -492,7 +503,7 @@ contract REVLoansFeeRecovery is TestBaseWorkflow {
|
|
|
492
503
|
// Normal borrow.
|
|
493
504
|
uint256 balBefore = USER.balance;
|
|
494
505
|
vm.prank(USER);
|
|
495
|
-
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(USER), 25);
|
|
506
|
+
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(USER), 25, USER);
|
|
496
507
|
uint256 normalReceived = USER.balance - balBefore;
|
|
497
508
|
|
|
498
509
|
// Revert to snapshot — identical state.
|
|
@@ -504,7 +515,7 @@ contract REVLoansFeeRecovery is TestBaseWorkflow {
|
|
|
504
515
|
|
|
505
516
|
balBefore = USER.balance;
|
|
506
517
|
vm.prank(USER);
|
|
507
|
-
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(USER), 25);
|
|
518
|
+
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(USER), 25, USER);
|
|
508
519
|
uint256 failReceived = USER.balance - balBefore;
|
|
509
520
|
|
|
510
521
|
// The borrower with a failed fee terminal should receive MORE than the normal borrower,
|
|
@@ -537,7 +548,7 @@ contract REVLoansFeeRecovery is TestBaseWorkflow {
|
|
|
537
548
|
// Normal borrow.
|
|
538
549
|
uint256 balBefore = USER.balance;
|
|
539
550
|
vm.prank(USER);
|
|
540
|
-
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens, payable(USER), 25);
|
|
551
|
+
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens, payable(USER), 25, USER);
|
|
541
552
|
uint256 normalReceived = USER.balance - balBefore;
|
|
542
553
|
|
|
543
554
|
// Get the actual borrow amount from the loan to compute expected REV fee.
|
|
@@ -555,7 +566,7 @@ contract REVLoansFeeRecovery is TestBaseWorkflow {
|
|
|
555
566
|
|
|
556
567
|
balBefore = USER.balance;
|
|
557
568
|
vm.prank(USER);
|
|
558
|
-
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens, payable(USER), 25);
|
|
569
|
+
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens, payable(USER), 25, USER);
|
|
559
570
|
uint256 failReceived = USER.balance - balBefore;
|
|
560
571
|
|
|
561
572
|
// The difference should be the REV fee amount.
|
|
@@ -594,7 +605,7 @@ contract REVLoansFeeRecovery is TestBaseWorkflow {
|
|
|
594
605
|
assertEq(allowanceBefore, 0, "No pre-existing allowance");
|
|
595
606
|
|
|
596
607
|
vm.prank(USER);
|
|
597
|
-
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(USER), 25);
|
|
608
|
+
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(USER), 25, USER);
|
|
598
609
|
|
|
599
610
|
// After the borrow, the allowance to the reverting terminal should still be 0
|
|
600
611
|
// (the catch block decreased it).
|
|
@@ -630,7 +641,7 @@ contract REVLoansFeeRecovery is TestBaseWorkflow {
|
|
|
630
641
|
// Normal borrow.
|
|
631
642
|
uint256 tokenBalBefore = TOKEN.balanceOf(USER);
|
|
632
643
|
vm.prank(USER);
|
|
633
|
-
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens, payable(USER), 25);
|
|
644
|
+
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens, payable(USER), 25, USER);
|
|
634
645
|
uint256 normalReceived = TOKEN.balanceOf(USER) - tokenBalBefore;
|
|
635
646
|
|
|
636
647
|
// Revert to snapshot.
|
|
@@ -642,7 +653,7 @@ contract REVLoansFeeRecovery is TestBaseWorkflow {
|
|
|
642
653
|
|
|
643
654
|
tokenBalBefore = TOKEN.balanceOf(USER);
|
|
644
655
|
vm.prank(USER);
|
|
645
|
-
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens, payable(USER), 25);
|
|
656
|
+
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens, payable(USER), 25, USER);
|
|
646
657
|
uint256 failReceived = TOKEN.balanceOf(USER) - tokenBalBefore;
|
|
647
658
|
|
|
648
659
|
// Failed-fee borrower should receive more tokens.
|
|
@@ -699,7 +710,7 @@ contract REVLoansFeeRecovery is TestBaseWorkflow {
|
|
|
699
710
|
REVLoanSource memory source = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: jbMultiTerminal()});
|
|
700
711
|
|
|
701
712
|
vm.prank(borrower);
|
|
702
|
-
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens, payable(borrower), 25);
|
|
713
|
+
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens, payable(borrower), 25, borrower);
|
|
703
714
|
}
|
|
704
715
|
|
|
705
716
|
// After 3 borrows with fee failures, no ETH should be stuck.
|
|
@@ -737,7 +748,7 @@ contract REVLoansFeeRecovery is TestBaseWorkflow {
|
|
|
737
748
|
|
|
738
749
|
uint256 balanceBefore = borrower.balance;
|
|
739
750
|
vm.prank(borrower);
|
|
740
|
-
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens, payable(borrower), 25);
|
|
751
|
+
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens, payable(borrower), 25, borrower);
|
|
741
752
|
uint256 received = borrower.balance - balanceBefore;
|
|
742
753
|
|
|
743
754
|
// The borrower should always receive something.
|
|
@@ -40,6 +40,8 @@ import {JBSuckerRegistry} from "@bananapus/suckers-v6/src/JBSuckerRegistry.sol";
|
|
|
40
40
|
import {JB721TiersHookDeployer} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
|
|
41
41
|
import {JB721TiersHook} from "@bananapus/721-hook-v6/src/JB721TiersHook.sol";
|
|
42
42
|
import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
|
|
43
|
+
import {JB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/JB721CheckpointsDeployer.sol";
|
|
44
|
+
import {IJB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/interfaces/IJB721CheckpointsDeployer.sol";
|
|
43
45
|
import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
|
|
44
46
|
import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
|
|
45
47
|
import {JBRuleset} from "@bananapus/core-v6/src/structs/JBRuleset.sol";
|
|
@@ -47,6 +49,7 @@ import {JBPayHookSpecification} from "@bananapus/core-v6/src/structs/JBPayHookSp
|
|
|
47
49
|
import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
|
|
48
50
|
import {REVOwner} from "../src/REVOwner.sol";
|
|
49
51
|
import {IREVDeployer} from "../src/interfaces/IREVDeployer.sol";
|
|
52
|
+
import {MockSuckerRegistry} from "./mock/MockSuckerRegistry.sol";
|
|
50
53
|
|
|
51
54
|
/// @notice A fake terminal that returns garbage accounting contexts.
|
|
52
55
|
/// Used to test unvalidated loan source terminal rejection.
|
|
@@ -198,7 +201,14 @@ contract REVLoansFindings is TestBaseWorkflow {
|
|
|
198
201
|
SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
|
|
199
202
|
HOOK_STORE = new JB721TiersHookStore();
|
|
200
203
|
EXAMPLE_HOOK = new JB721TiersHook(
|
|
201
|
-
jbDirectory(),
|
|
204
|
+
jbDirectory(),
|
|
205
|
+
jbPermissions(),
|
|
206
|
+
jbPrices(),
|
|
207
|
+
jbRulesets(),
|
|
208
|
+
HOOK_STORE,
|
|
209
|
+
jbSplits(),
|
|
210
|
+
IJB721CheckpointsDeployer(address(new JB721CheckpointsDeployer())),
|
|
211
|
+
multisig()
|
|
202
212
|
);
|
|
203
213
|
ADDRESS_REGISTRY = new JBAddressRegistry();
|
|
204
214
|
HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
|
|
@@ -207,7 +217,7 @@ contract REVLoansFindings is TestBaseWorkflow {
|
|
|
207
217
|
|
|
208
218
|
LOANS_CONTRACT = new REVLoans({
|
|
209
219
|
controller: jbController(),
|
|
210
|
-
|
|
220
|
+
suckerRegistry: IJBSuckerRegistry(address(new MockSuckerRegistry())),
|
|
211
221
|
revId: FEE_PROJECT_ID,
|
|
212
222
|
owner: address(this),
|
|
213
223
|
permit2: permit2(),
|
|
@@ -219,7 +229,8 @@ contract REVLoansFindings is TestBaseWorkflow {
|
|
|
219
229
|
jbDirectory(),
|
|
220
230
|
FEE_PROJECT_ID,
|
|
221
231
|
SUCKER_REGISTRY,
|
|
222
|
-
address(LOANS_CONTRACT)
|
|
232
|
+
address(LOANS_CONTRACT),
|
|
233
|
+
address(0)
|
|
223
234
|
);
|
|
224
235
|
|
|
225
236
|
REV_DEPLOYER = new REVDeployer{salt: REV_DEPLOYER_SALT}(
|
|
@@ -372,7 +383,7 @@ contract REVLoansFindings is TestBaseWorkflow {
|
|
|
372
383
|
REVLoanSource memory source = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: jbMultiTerminal()});
|
|
373
384
|
|
|
374
385
|
vm.prank(USER);
|
|
375
|
-
(loanId, loan) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, loanable, tokens, payable(USER), 25);
|
|
386
|
+
(loanId, loan) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, loanable, tokens, payable(USER), 25, USER);
|
|
376
387
|
}
|
|
377
388
|
|
|
378
389
|
//*********************************************************************//
|
|
@@ -411,7 +422,7 @@ contract REVLoansFindings is TestBaseWorkflow {
|
|
|
411
422
|
);
|
|
412
423
|
|
|
413
424
|
vm.prank(USER);
|
|
414
|
-
LOANS_CONTRACT.borrowFrom(REVNET_ID, fakeSource, loanable, tokens, payable(USER), 25);
|
|
425
|
+
LOANS_CONTRACT.borrowFrom(REVNET_ID, fakeSource, loanable, tokens, payable(USER), 25, USER);
|
|
415
426
|
}
|
|
416
427
|
|
|
417
428
|
//*********************************************************************//
|
|
@@ -35,6 +35,8 @@ import {JBSuckerRegistry} from "@bananapus/suckers-v6/src/JBSuckerRegistry.sol";
|
|
|
35
35
|
import {JB721TiersHookDeployer} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
|
|
36
36
|
import {JB721TiersHook} from "@bananapus/721-hook-v6/src/JB721TiersHook.sol";
|
|
37
37
|
import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
|
|
38
|
+
import {JB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/JB721CheckpointsDeployer.sol";
|
|
39
|
+
import {IJB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/interfaces/IJB721CheckpointsDeployer.sol";
|
|
38
40
|
import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
|
|
39
41
|
import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
|
|
40
42
|
import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
|
|
@@ -43,6 +45,7 @@ import {JBPayHookSpecification} from "@bananapus/core-v6/src/structs/JBPayHookSp
|
|
|
43
45
|
import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
|
|
44
46
|
import {REVOwner} from "../src/REVOwner.sol";
|
|
45
47
|
import {IREVDeployer} from "../src/interfaces/IREVDeployer.sol";
|
|
48
|
+
import {MockSuckerRegistry} from "./mock/MockSuckerRegistry.sol";
|
|
46
49
|
|
|
47
50
|
/// @notice A fake terminal that tracks whether useAllowanceOf was called.
|
|
48
51
|
/// @dev REVLoans.borrowFrom does not validate source terminal registration.
|
|
@@ -193,7 +196,14 @@ contract REVLoansRegressions is TestBaseWorkflow {
|
|
|
193
196
|
SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
|
|
194
197
|
HOOK_STORE = new JB721TiersHookStore();
|
|
195
198
|
EXAMPLE_HOOK = new JB721TiersHook(
|
|
196
|
-
jbDirectory(),
|
|
199
|
+
jbDirectory(),
|
|
200
|
+
jbPermissions(),
|
|
201
|
+
jbPrices(),
|
|
202
|
+
jbRulesets(),
|
|
203
|
+
HOOK_STORE,
|
|
204
|
+
jbSplits(),
|
|
205
|
+
IJB721CheckpointsDeployer(address(new JB721CheckpointsDeployer())),
|
|
206
|
+
multisig()
|
|
197
207
|
);
|
|
198
208
|
ADDRESS_REGISTRY = new JBAddressRegistry();
|
|
199
209
|
HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
|
|
@@ -202,7 +212,7 @@ contract REVLoansRegressions is TestBaseWorkflow {
|
|
|
202
212
|
|
|
203
213
|
LOANS_CONTRACT = new REVLoans({
|
|
204
214
|
controller: jbController(),
|
|
205
|
-
|
|
215
|
+
suckerRegistry: IJBSuckerRegistry(address(new MockSuckerRegistry())),
|
|
206
216
|
revId: FEE_PROJECT_ID,
|
|
207
217
|
owner: address(this),
|
|
208
218
|
permit2: permit2(),
|
|
@@ -214,7 +224,8 @@ contract REVLoansRegressions is TestBaseWorkflow {
|
|
|
214
224
|
jbDirectory(),
|
|
215
225
|
FEE_PROJECT_ID,
|
|
216
226
|
SUCKER_REGISTRY,
|
|
217
|
-
address(LOANS_CONTRACT)
|
|
227
|
+
address(LOANS_CONTRACT),
|
|
228
|
+
address(0)
|
|
218
229
|
);
|
|
219
230
|
|
|
220
231
|
REV_DEPLOYER = new REVDeployer{salt: REV_DEPLOYER_SALT}(
|
|
@@ -335,7 +346,7 @@ contract REVLoansRegressions is TestBaseWorkflow {
|
|
|
335
346
|
);
|
|
336
347
|
|
|
337
348
|
vm.prank(USER);
|
|
338
|
-
LOANS_CONTRACT.borrowFrom(REVNET_ID, fakeSource, borrowable, tokens, payable(USER), 500);
|
|
349
|
+
LOANS_CONTRACT.borrowFrom(REVNET_ID, fakeSource, borrowable, tokens, payable(USER), 500, USER);
|
|
339
350
|
}
|
|
340
351
|
|
|
341
352
|
/// @notice Verify that the configured loan source (real terminal) is properly registered.
|
|
@@ -35,11 +35,14 @@ import {JBSuckerRegistry} from "@bananapus/suckers-v6/src/JBSuckerRegistry.sol";
|
|
|
35
35
|
import {JB721TiersHookDeployer} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
|
|
36
36
|
import {JB721TiersHook} from "@bananapus/721-hook-v6/src/JB721TiersHook.sol";
|
|
37
37
|
import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
|
|
38
|
+
import {JB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/JB721CheckpointsDeployer.sol";
|
|
39
|
+
import {IJB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/interfaces/IJB721CheckpointsDeployer.sol";
|
|
38
40
|
import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
|
|
39
41
|
import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
|
|
40
42
|
import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
|
|
41
43
|
import {REVOwner} from "../src/REVOwner.sol";
|
|
42
44
|
import {IREVDeployer} from "../src/interfaces/IREVDeployer.sol";
|
|
45
|
+
import {MockSuckerRegistry} from "./mock/MockSuckerRegistry.sol";
|
|
43
46
|
|
|
44
47
|
struct SourceFeeProjectConfig {
|
|
45
48
|
REVConfig configuration;
|
|
@@ -220,7 +223,14 @@ contract REVLoansSourceFeeRecovery is TestBaseWorkflow {
|
|
|
220
223
|
SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
|
|
221
224
|
HOOK_STORE = new JB721TiersHookStore();
|
|
222
225
|
EXAMPLE_HOOK = new JB721TiersHook(
|
|
223
|
-
jbDirectory(),
|
|
226
|
+
jbDirectory(),
|
|
227
|
+
jbPermissions(),
|
|
228
|
+
jbPrices(),
|
|
229
|
+
jbRulesets(),
|
|
230
|
+
HOOK_STORE,
|
|
231
|
+
jbSplits(),
|
|
232
|
+
IJB721CheckpointsDeployer(address(new JB721CheckpointsDeployer())),
|
|
233
|
+
multisig()
|
|
224
234
|
);
|
|
225
235
|
ADDRESS_REGISTRY = new JBAddressRegistry();
|
|
226
236
|
HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
|
|
@@ -229,7 +239,7 @@ contract REVLoansSourceFeeRecovery is TestBaseWorkflow {
|
|
|
229
239
|
|
|
230
240
|
LOANS_CONTRACT = new REVLoans({
|
|
231
241
|
controller: jbController(),
|
|
232
|
-
|
|
242
|
+
suckerRegistry: IJBSuckerRegistry(address(new MockSuckerRegistry())),
|
|
233
243
|
revId: FEE_PROJECT_ID,
|
|
234
244
|
owner: address(this),
|
|
235
245
|
permit2: permit2(),
|
|
@@ -241,7 +251,8 @@ contract REVLoansSourceFeeRecovery is TestBaseWorkflow {
|
|
|
241
251
|
jbDirectory(),
|
|
242
252
|
FEE_PROJECT_ID,
|
|
243
253
|
SUCKER_REGISTRY,
|
|
244
|
-
address(LOANS_CONTRACT)
|
|
254
|
+
address(LOANS_CONTRACT),
|
|
255
|
+
address(0)
|
|
245
256
|
);
|
|
246
257
|
|
|
247
258
|
REV_DEPLOYER = new REVDeployer{salt: REV_DEPLOYER_SALT}(
|
|
@@ -310,7 +321,7 @@ contract REVLoansSourceFeeRecovery is TestBaseWorkflow {
|
|
|
310
321
|
REVLoanSource memory source = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: jbMultiTerminal()});
|
|
311
322
|
|
|
312
323
|
vm.prank(user);
|
|
313
|
-
(loanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(user), 25);
|
|
324
|
+
(loanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(user), 25, user);
|
|
314
325
|
}
|
|
315
326
|
|
|
316
327
|
// =========================================================================
|
|
@@ -495,7 +506,7 @@ contract REVLoansSourceFeeRecovery is TestBaseWorkflow {
|
|
|
495
506
|
|
|
496
507
|
uint256 balBefore = USER.balance;
|
|
497
508
|
vm.prank(USER);
|
|
498
|
-
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(USER), 25);
|
|
509
|
+
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(USER), 25, USER);
|
|
499
510
|
|
|
500
511
|
uint256 received = USER.balance - balBefore;
|
|
501
512
|
assertGt(received, 0, "Borrower should receive ETH even when source fee terminal fails");
|