@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.
- 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 +17 -3
- package/package.json +2 -2
- package/references/operations.md +1 -1
- package/script/Deploy.s.sol +25 -6
- package/src/REVHiddenTokens.sol +149 -0
- package/src/REVLoans.sol +115 -144
- package/src/REVOwner.sol +11 -3
- package/src/interfaces/IREVHiddenTokens.sol +53 -0
- package/src/interfaces/IREVLoans.sol +3 -6
- package/test/REV.integrations.t.sol +2 -1
- package/test/REVAutoIssuanceFuzz.t.sol +2 -1
- package/test/REVDeployerRegressions.t.sol +2 -2
- package/test/REVInvincibility.t.sol +6 -6
- package/test/REVInvincibilityHandler.sol +1 -1
- package/test/REVLifecycle.t.sol +2 -2
- package/test/REVLoans.invariants.t.sol +3 -3
- package/test/REVLoansAttacks.t.sol +7 -6
- package/test/REVLoansFeeRecovery.t.sol +12 -12
- package/test/REVLoansFindings.t.sol +4 -4
- package/test/REVLoansRegressions.t.sol +3 -3
- package/test/REVLoansSourceFeeRecovery.t.sol +4 -4
- package/test/REVLoansSourced.t.sol +48 -24
- package/test/REVLoansUnSourced.t.sol +3 -3
- package/test/TestBurnHeldTokens.t.sol +2 -2
- package/test/TestCEIPattern.t.sol +7 -6
- package/test/TestCashOutCallerValidation.t.sol +2 -2
- package/test/TestConversionDocumentation.t.sol +2 -2
- package/test/TestCrossCurrencyReclaim.t.sol +2 -2
- package/test/TestCrossSourceReallocation.t.sol +3 -3
- package/test/TestERC2771MetaTx.t.sol +6 -4
- package/test/TestEmptyBuybackSpecs.t.sol +2 -2
- package/test/TestFlashLoanSurplus.t.sol +3 -3
- package/test/TestHiddenTokens.t.sol +420 -0
- package/test/TestHookArrayOOB.t.sol +2 -2
- package/test/TestLiquidationBehavior.t.sol +4 -4
- package/test/TestLoanSourceRotation.t.sol +8 -6
- package/test/TestLoansCashOutDelay.t.sol +6 -6
- package/test/TestLongTailEconomics.t.sol +2 -2
- package/test/TestLowFindings.t.sol +13 -8
- package/test/TestMixedFixes.t.sol +7 -7
- package/test/TestPermit2Signatures.t.sol +3 -3
- package/test/TestReallocationSandwich.t.sol +4 -3
- package/test/TestRevnetRegressions.t.sol +3 -4
- package/test/TestSplitWeightAdjustment.t.sol +4 -3
- package/test/TestSplitWeightE2E.t.sol +4 -3
- package/test/TestSplitWeightFork.t.sol +2 -2
- package/test/TestStageTransitionBorrowable.t.sol +2 -2
- package/test/TestSwapTerminalPermission.t.sol +2 -2
- package/test/TestUint112Overflow.t.sol +3 -3
- package/test/TestZeroAmountLoanGuard.t.sol +3 -3
- package/test/TestZeroRepayment.t.sol +3 -3
- package/test/audit/LoanIdOverflowGuard.t.sol +4 -4
- package/test/audit/NemesisOperatorDelegation.t.sol +278 -0
- package/test/fork/ForkTestBase.sol +4 -3
- 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/regression/TestBurnPermissionRequired.t.sol +4 -4
- package/test/regression/TestCashOutBuybackFeeLeak.t.sol +2 -2
- package/test/regression/TestCrossRevnetLiquidation.t.sol +2 -2
- package/test/regression/TestCumulativeLoanCounter.t.sol +3 -3
- package/test/regression/TestLiquidateGapHandling.t.sol +3 -3
- package/test/regression/TestZeroPriceFeed.t.sol +5 -5
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
import {IJBController} from "@bananapus/core-v6/src/interfaces/IJBController.sol";
|
|
5
|
+
|
|
6
|
+
/// @notice Manages hiding (burning) and revealing (re-minting) revnet tokens to exclude them from totalSupply.
|
|
7
|
+
interface IREVHiddenTokens {
|
|
8
|
+
/// @notice Emitted when tokens are hidden (burned and tracked for later reveal).
|
|
9
|
+
/// @param revnetId The ID of the revnet whose tokens are hidden.
|
|
10
|
+
/// @param tokenCount The number of tokens hidden.
|
|
11
|
+
/// @param holder The address whose tokens are hidden.
|
|
12
|
+
/// @param caller The address that hid the tokens.
|
|
13
|
+
event HideTokens(uint256 indexed revnetId, uint256 tokenCount, address holder, address caller);
|
|
14
|
+
|
|
15
|
+
/// @notice Emitted when previously hidden tokens are revealed (re-minted).
|
|
16
|
+
/// @param revnetId The ID of the revnet whose tokens are revealed.
|
|
17
|
+
/// @param tokenCount The number of tokens revealed.
|
|
18
|
+
/// @param beneficiary The address receiving the revealed tokens.
|
|
19
|
+
/// @param holder The address whose hidden balance is decremented.
|
|
20
|
+
/// @param caller The address that revealed the tokens.
|
|
21
|
+
event RevealTokens(
|
|
22
|
+
uint256 indexed revnetId, uint256 tokenCount, address beneficiary, address holder, address caller
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
/// @notice The controller that manages revnets using this contract.
|
|
26
|
+
/// @return The controller contract.
|
|
27
|
+
function CONTROLLER() external view returns (IJBController);
|
|
28
|
+
|
|
29
|
+
/// @notice The number of tokens a holder has hidden for a given revnet.
|
|
30
|
+
/// @param holder The address of the token holder.
|
|
31
|
+
/// @param revnetId The ID of the revnet.
|
|
32
|
+
/// @return The number of hidden tokens.
|
|
33
|
+
function hiddenBalanceOf(address holder, uint256 revnetId) external view returns (uint256);
|
|
34
|
+
|
|
35
|
+
/// @notice The total number of hidden tokens for a revnet.
|
|
36
|
+
/// @param revnetId The ID of the revnet.
|
|
37
|
+
/// @return The total hidden token count.
|
|
38
|
+
function totalHiddenOf(uint256 revnetId) external view returns (uint256);
|
|
39
|
+
|
|
40
|
+
/// @notice Hide tokens by burning them and tracking them for later reveal.
|
|
41
|
+
/// @dev The holder must have granted BURN_TOKENS permission to this contract.
|
|
42
|
+
/// @param revnetId The ID of the revnet whose tokens to hide.
|
|
43
|
+
/// @param tokenCount The number of tokens to hide.
|
|
44
|
+
/// @param holder The address whose tokens to hide.
|
|
45
|
+
function hideTokensOf(uint256 revnetId, uint256 tokenCount, address holder) external;
|
|
46
|
+
|
|
47
|
+
/// @notice Reveal previously hidden tokens by re-minting them.
|
|
48
|
+
/// @param revnetId The ID of the revnet whose tokens to reveal.
|
|
49
|
+
/// @param tokenCount The number of tokens to reveal.
|
|
50
|
+
/// @param beneficiary The address that will receive the revealed tokens.
|
|
51
|
+
/// @param holder The address whose hidden balance to decrement.
|
|
52
|
+
function revealTokensOf(uint256 revnetId, uint256 tokenCount, address beneficiary, address holder) external;
|
|
53
|
+
}
|
|
@@ -5,7 +5,6 @@ import {IJBController} from "@bananapus/core-v6/src/interfaces/IJBController.sol
|
|
|
5
5
|
import {IJBDirectory} from "@bananapus/core-v6/src/interfaces/IJBDirectory.sol";
|
|
6
6
|
import {IJBPayoutTerminal} from "@bananapus/core-v6/src/interfaces/IJBPayoutTerminal.sol";
|
|
7
7
|
import {IJBPrices} from "@bananapus/core-v6/src/interfaces/IJBPrices.sol";
|
|
8
|
-
import {IJBProjects} from "@bananapus/core-v6/src/interfaces/IJBProjects.sol";
|
|
9
8
|
import {IJBTokenUriResolver} from "@bananapus/core-v6/src/interfaces/IJBTokenUriResolver.sol";
|
|
10
9
|
import {JBSingleAllowance} from "@bananapus/core-v6/src/structs/JBSingleAllowance.sol";
|
|
11
10
|
import {IPermit2} from "@uniswap/permit2/src/interfaces/IPermit2.sol";
|
|
@@ -164,10 +163,6 @@ interface IREVLoans {
|
|
|
164
163
|
/// @return The prices contract.
|
|
165
164
|
function PRICES() external view returns (IJBPrices);
|
|
166
165
|
|
|
167
|
-
/// @notice The contract that mints ERC-721s representing project ownership.
|
|
168
|
-
/// @return The projects contract.
|
|
169
|
-
function PROJECTS() external view returns (IJBProjects);
|
|
170
|
-
|
|
171
166
|
/// @notice The ID of the REV revnet that receives protocol fees from loans.
|
|
172
167
|
/// @return The REV revnet ID.
|
|
173
168
|
function REV_ID() external view returns (uint256);
|
|
@@ -219,6 +214,7 @@ interface IREVLoans {
|
|
|
219
214
|
/// @param collateralCount The amount of tokens to use as collateral for the loan.
|
|
220
215
|
/// @param beneficiary The address that will receive the borrowed funds and fee payment tokens.
|
|
221
216
|
/// @param prepaidFeePercent The fee percent to charge upfront, in terms of `JBConstants.MAX_FEE`.
|
|
217
|
+
/// @param holder The address whose tokens are used as collateral and who receives the loan NFT.
|
|
222
218
|
/// @return loanId The ID of the loan created from borrowing.
|
|
223
219
|
/// @return The loan created from borrowing.
|
|
224
220
|
function borrowFrom(
|
|
@@ -227,7 +223,8 @@ interface IREVLoans {
|
|
|
227
223
|
uint256 minBorrowAmount,
|
|
228
224
|
uint256 collateralCount,
|
|
229
225
|
address payable beneficiary,
|
|
230
|
-
uint256 prepaidFeePercent
|
|
226
|
+
uint256 prepaidFeePercent,
|
|
227
|
+
address holder
|
|
231
228
|
)
|
|
232
229
|
external
|
|
233
230
|
returns (uint256 loanId, REVLoan memory);
|
|
@@ -92,7 +92,6 @@ contract REVDeployerRegressions is TestBaseWorkflow {
|
|
|
92
92
|
|
|
93
93
|
LOANS_CONTRACT = new REVLoans({
|
|
94
94
|
controller: jbController(),
|
|
95
|
-
projects: jbProjects(),
|
|
96
95
|
revId: FEE_PROJECT_ID,
|
|
97
96
|
owner: address(this),
|
|
98
97
|
permit2: permit2(),
|
|
@@ -104,7 +103,8 @@ contract REVDeployerRegressions is TestBaseWorkflow {
|
|
|
104
103
|
jbDirectory(),
|
|
105
104
|
FEE_PROJECT_ID,
|
|
106
105
|
SUCKER_REGISTRY,
|
|
107
|
-
address(LOANS_CONTRACT)
|
|
106
|
+
address(LOANS_CONTRACT),
|
|
107
|
+
address(0)
|
|
108
108
|
);
|
|
109
109
|
|
|
110
110
|
REV_DEPLOYER = new REVDeployer{salt: REV_DEPLOYER_SALT}(
|
|
@@ -244,7 +244,6 @@ contract REVInvincibility_PropertyTests is TestBaseWorkflow {
|
|
|
244
244
|
|
|
245
245
|
LOANS_CONTRACT = new REVLoans({
|
|
246
246
|
controller: jbController(),
|
|
247
|
-
projects: jbProjects(),
|
|
248
247
|
revId: FEE_PROJECT_ID,
|
|
249
248
|
owner: address(this),
|
|
250
249
|
permit2: permit2(),
|
|
@@ -256,7 +255,8 @@ contract REVInvincibility_PropertyTests is TestBaseWorkflow {
|
|
|
256
255
|
jbDirectory(),
|
|
257
256
|
FEE_PROJECT_ID,
|
|
258
257
|
SUCKER_REGISTRY,
|
|
259
|
-
address(LOANS_CONTRACT)
|
|
258
|
+
address(LOANS_CONTRACT),
|
|
259
|
+
address(0)
|
|
260
260
|
);
|
|
261
261
|
|
|
262
262
|
REV_DEPLOYER = new REVDeployer{salt: REV_DEPLOYER_SALT}(
|
|
@@ -329,7 +329,7 @@ contract REVInvincibility_PropertyTests is TestBaseWorkflow {
|
|
|
329
329
|
REVLoanSource memory source = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: jbMultiTerminal()});
|
|
330
330
|
|
|
331
331
|
vm.prank(user);
|
|
332
|
-
(loanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(user), prepaidFee);
|
|
332
|
+
(loanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(user), prepaidFee, user);
|
|
333
333
|
}
|
|
334
334
|
|
|
335
335
|
// =====================================================================
|
|
@@ -788,7 +788,7 @@ contract REVInvincibility_PropertyTests is TestBaseWorkflow {
|
|
|
788
788
|
|
|
789
789
|
if (borrowableA > 0) {
|
|
790
790
|
vm.prank(userA);
|
|
791
|
-
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokensA, payable(userA), 25);
|
|
791
|
+
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokensA, payable(userA), 25, userA);
|
|
792
792
|
}
|
|
793
793
|
|
|
794
794
|
// UserB's tokens should still have proportional cash-out value
|
|
@@ -1028,7 +1028,6 @@ contract REVInvincibility_Invariants is StdInvariant, TestBaseWorkflow {
|
|
|
1028
1028
|
|
|
1029
1029
|
LOANS_CONTRACT = new REVLoans({
|
|
1030
1030
|
controller: jbController(),
|
|
1031
|
-
projects: jbProjects(),
|
|
1032
1031
|
revId: FEE_PROJECT_ID,
|
|
1033
1032
|
owner: address(this),
|
|
1034
1033
|
permit2: permit2(),
|
|
@@ -1040,7 +1039,8 @@ contract REVInvincibility_Invariants is StdInvariant, TestBaseWorkflow {
|
|
|
1040
1039
|
jbDirectory(),
|
|
1041
1040
|
FEE_PROJECT_ID,
|
|
1042
1041
|
SUCKER_REGISTRY,
|
|
1043
|
-
address(LOANS_CONTRACT)
|
|
1042
|
+
address(LOANS_CONTRACT),
|
|
1043
|
+
address(0)
|
|
1044
1044
|
);
|
|
1045
1045
|
|
|
1046
1046
|
REV_DEPLOYER = new REVDeployer{salt: REV_DEPLOYER_SALT}(
|
|
@@ -145,7 +145,7 @@ contract REVInvincibilityHandler is JBTest {
|
|
|
145
145
|
|
|
146
146
|
REVLoanSource memory source = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: TERMINAL});
|
|
147
147
|
(, REVLoan memory loan) =
|
|
148
|
-
LOANS.borrowFrom(REVNET_ID, source, borrowable, receivedTokens, payable(USER), prepaidFee);
|
|
148
|
+
LOANS.borrowFrom(REVNET_ID, source, borrowable, receivedTokens, payable(USER), prepaidFee, USER);
|
|
149
149
|
|
|
150
150
|
COLLATERAL_SUM += receivedTokens;
|
|
151
151
|
BORROWED_SUM += loan.amount;
|
package/test/REVLifecycle.t.sol
CHANGED
|
@@ -100,7 +100,6 @@ contract REVLifecycle_Local is TestBaseWorkflow {
|
|
|
100
100
|
|
|
101
101
|
LOANS_CONTRACT = new REVLoans({
|
|
102
102
|
controller: jbController(),
|
|
103
|
-
projects: jbProjects(),
|
|
104
103
|
revId: FEE_PROJECT_ID,
|
|
105
104
|
owner: address(this),
|
|
106
105
|
permit2: permit2(),
|
|
@@ -112,7 +111,8 @@ contract REVLifecycle_Local is TestBaseWorkflow {
|
|
|
112
111
|
jbDirectory(),
|
|
113
112
|
FEE_PROJECT_ID,
|
|
114
113
|
SUCKER_REGISTRY,
|
|
115
|
-
address(LOANS_CONTRACT)
|
|
114
|
+
address(LOANS_CONTRACT),
|
|
115
|
+
address(0)
|
|
116
116
|
);
|
|
117
117
|
|
|
118
118
|
REV_DEPLOYER = new REVDeployer{salt: REV_DEPLOYER_SALT}(
|
|
@@ -117,7 +117,7 @@ contract REVLoansCallHandler is JBTest {
|
|
|
117
117
|
|
|
118
118
|
REVLoanSource memory sauce = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: TERMINAL});
|
|
119
119
|
(, REVLoan memory lastLoan) =
|
|
120
|
-
LOANS.borrowFrom(REVNET_ID, sauce, borrowable, receivedTokens, payable(USER), prepaidFee);
|
|
120
|
+
LOANS.borrowFrom(REVNET_ID, sauce, borrowable, receivedTokens, payable(USER), prepaidFee, USER);
|
|
121
121
|
|
|
122
122
|
COLLATERAL_SUM += receivedTokens;
|
|
123
123
|
BORROWED_SUM += lastLoan.amount;
|
|
@@ -542,7 +542,6 @@ contract InvariantREVLoansTests is StdInvariant, TestBaseWorkflow {
|
|
|
542
542
|
|
|
543
543
|
LOANS_CONTRACT = new REVLoans({
|
|
544
544
|
controller: jbController(),
|
|
545
|
-
projects: jbProjects(),
|
|
546
545
|
revId: FEE_PROJECT_ID,
|
|
547
546
|
owner: address(this),
|
|
548
547
|
permit2: permit2(),
|
|
@@ -554,7 +553,8 @@ contract InvariantREVLoansTests is StdInvariant, TestBaseWorkflow {
|
|
|
554
553
|
jbDirectory(),
|
|
555
554
|
FEE_PROJECT_ID,
|
|
556
555
|
SUCKER_REGISTRY,
|
|
557
|
-
address(LOANS_CONTRACT)
|
|
556
|
+
address(LOANS_CONTRACT),
|
|
557
|
+
address(0)
|
|
558
558
|
);
|
|
559
559
|
|
|
560
560
|
REV_DEPLOYER = new REVDeployer{salt: REV_DEPLOYER_SALT}(
|
|
@@ -98,7 +98,8 @@ contract ReentrantTerminal is ERC165, IJBPayoutTerminal {
|
|
|
98
98
|
0, // minBorrowAmount
|
|
99
99
|
reenterCollateral,
|
|
100
100
|
payable(address(this)),
|
|
101
|
-
25 // MIN_PREPAID_FEE_PERCENT
|
|
101
|
+
25, // MIN_PREPAID_FEE_PERCENT
|
|
102
|
+
address(this)
|
|
102
103
|
) {}
|
|
103
104
|
catch {
|
|
104
105
|
// Expected to revert if reentrancy guard exists
|
|
@@ -383,7 +384,6 @@ contract REVLoansAttacks is TestBaseWorkflow {
|
|
|
383
384
|
|
|
384
385
|
LOANS_CONTRACT = new REVLoans({
|
|
385
386
|
controller: jbController(),
|
|
386
|
-
projects: jbProjects(),
|
|
387
387
|
revId: FEE_PROJECT_ID,
|
|
388
388
|
owner: address(this),
|
|
389
389
|
permit2: permit2(),
|
|
@@ -395,7 +395,8 @@ contract REVLoansAttacks is TestBaseWorkflow {
|
|
|
395
395
|
jbDirectory(),
|
|
396
396
|
FEE_PROJECT_ID,
|
|
397
397
|
SUCKER_REGISTRY,
|
|
398
|
-
address(LOANS_CONTRACT)
|
|
398
|
+
address(LOANS_CONTRACT),
|
|
399
|
+
address(0)
|
|
399
400
|
);
|
|
400
401
|
|
|
401
402
|
REV_DEPLOYER = new REVDeployer{salt: REV_DEPLOYER_SALT}(
|
|
@@ -474,7 +475,7 @@ contract REVLoansAttacks is TestBaseWorkflow {
|
|
|
474
475
|
REVLoanSource memory source = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: jbMultiTerminal()});
|
|
475
476
|
|
|
476
477
|
vm.prank(user);
|
|
477
|
-
(loanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(user), prepaidFee);
|
|
478
|
+
(loanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(user), prepaidFee, user);
|
|
478
479
|
}
|
|
479
480
|
|
|
480
481
|
// =========================================================================
|
|
@@ -646,7 +647,7 @@ contract REVLoansAttacks is TestBaseWorkflow {
|
|
|
646
647
|
vm.assume(borrowable > 0);
|
|
647
648
|
|
|
648
649
|
vm.prank(userA);
|
|
649
|
-
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokensA, payable(userA), 25);
|
|
650
|
+
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokensA, payable(userA), 25, userA);
|
|
650
651
|
|
|
651
652
|
// After borrowing, tokensA are burned as collateral
|
|
652
653
|
// But the surplus is adjusted by adding totalBorrowed
|
|
@@ -771,7 +772,7 @@ contract REVLoansAttacks is TestBaseWorkflow {
|
|
|
771
772
|
|
|
772
773
|
// Borrow with max prepaid fee (so no additional fee on immediate repay)
|
|
773
774
|
vm.prank(USER);
|
|
774
|
-
(uint256 loanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens, payable(USER), 500);
|
|
775
|
+
(uint256 loanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens, payable(USER), 500, USER);
|
|
775
776
|
|
|
776
777
|
REVLoan memory loan = LOANS_CONTRACT.loanOf(loanId);
|
|
777
778
|
|
|
@@ -349,7 +349,6 @@ contract REVLoansFeeRecovery is TestBaseWorkflow {
|
|
|
349
349
|
|
|
350
350
|
LOANS_CONTRACT = new REVLoans({
|
|
351
351
|
controller: jbController(),
|
|
352
|
-
projects: jbProjects(),
|
|
353
352
|
revId: FEE_PROJECT_ID,
|
|
354
353
|
owner: address(this),
|
|
355
354
|
permit2: permit2(),
|
|
@@ -361,7 +360,8 @@ contract REVLoansFeeRecovery is TestBaseWorkflow {
|
|
|
361
360
|
jbDirectory(),
|
|
362
361
|
FEE_PROJECT_ID,
|
|
363
362
|
SUCKER_REGISTRY,
|
|
364
|
-
address(LOANS_CONTRACT)
|
|
363
|
+
address(LOANS_CONTRACT),
|
|
364
|
+
address(0)
|
|
365
365
|
);
|
|
366
366
|
|
|
367
367
|
REV_DEPLOYER = new REVDeployer{salt: REV_DEPLOYER_SALT}(
|
|
@@ -450,7 +450,7 @@ contract REVLoansFeeRecovery is TestBaseWorkflow {
|
|
|
450
450
|
borrowerBalanceBefore = user.balance;
|
|
451
451
|
|
|
452
452
|
vm.prank(user);
|
|
453
|
-
(loanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(user), prepaidFee);
|
|
453
|
+
(loanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(user), prepaidFee, user);
|
|
454
454
|
|
|
455
455
|
borrowerBalanceAfter = user.balance;
|
|
456
456
|
}
|
|
@@ -492,7 +492,7 @@ contract REVLoansFeeRecovery is TestBaseWorkflow {
|
|
|
492
492
|
// Normal borrow.
|
|
493
493
|
uint256 balBefore = USER.balance;
|
|
494
494
|
vm.prank(USER);
|
|
495
|
-
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(USER), 25);
|
|
495
|
+
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(USER), 25, USER);
|
|
496
496
|
uint256 normalReceived = USER.balance - balBefore;
|
|
497
497
|
|
|
498
498
|
// Revert to snapshot — identical state.
|
|
@@ -504,7 +504,7 @@ contract REVLoansFeeRecovery is TestBaseWorkflow {
|
|
|
504
504
|
|
|
505
505
|
balBefore = USER.balance;
|
|
506
506
|
vm.prank(USER);
|
|
507
|
-
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(USER), 25);
|
|
507
|
+
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(USER), 25, USER);
|
|
508
508
|
uint256 failReceived = USER.balance - balBefore;
|
|
509
509
|
|
|
510
510
|
// The borrower with a failed fee terminal should receive MORE than the normal borrower,
|
|
@@ -537,7 +537,7 @@ contract REVLoansFeeRecovery is TestBaseWorkflow {
|
|
|
537
537
|
// Normal borrow.
|
|
538
538
|
uint256 balBefore = USER.balance;
|
|
539
539
|
vm.prank(USER);
|
|
540
|
-
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens, payable(USER), 25);
|
|
540
|
+
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens, payable(USER), 25, USER);
|
|
541
541
|
uint256 normalReceived = USER.balance - balBefore;
|
|
542
542
|
|
|
543
543
|
// Get the actual borrow amount from the loan to compute expected REV fee.
|
|
@@ -555,7 +555,7 @@ contract REVLoansFeeRecovery is TestBaseWorkflow {
|
|
|
555
555
|
|
|
556
556
|
balBefore = USER.balance;
|
|
557
557
|
vm.prank(USER);
|
|
558
|
-
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens, payable(USER), 25);
|
|
558
|
+
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens, payable(USER), 25, USER);
|
|
559
559
|
uint256 failReceived = USER.balance - balBefore;
|
|
560
560
|
|
|
561
561
|
// The difference should be the REV fee amount.
|
|
@@ -594,7 +594,7 @@ contract REVLoansFeeRecovery is TestBaseWorkflow {
|
|
|
594
594
|
assertEq(allowanceBefore, 0, "No pre-existing allowance");
|
|
595
595
|
|
|
596
596
|
vm.prank(USER);
|
|
597
|
-
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(USER), 25);
|
|
597
|
+
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(USER), 25, USER);
|
|
598
598
|
|
|
599
599
|
// After the borrow, the allowance to the reverting terminal should still be 0
|
|
600
600
|
// (the catch block decreased it).
|
|
@@ -630,7 +630,7 @@ contract REVLoansFeeRecovery is TestBaseWorkflow {
|
|
|
630
630
|
// Normal borrow.
|
|
631
631
|
uint256 tokenBalBefore = TOKEN.balanceOf(USER);
|
|
632
632
|
vm.prank(USER);
|
|
633
|
-
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens, payable(USER), 25);
|
|
633
|
+
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens, payable(USER), 25, USER);
|
|
634
634
|
uint256 normalReceived = TOKEN.balanceOf(USER) - tokenBalBefore;
|
|
635
635
|
|
|
636
636
|
// Revert to snapshot.
|
|
@@ -642,7 +642,7 @@ contract REVLoansFeeRecovery is TestBaseWorkflow {
|
|
|
642
642
|
|
|
643
643
|
tokenBalBefore = TOKEN.balanceOf(USER);
|
|
644
644
|
vm.prank(USER);
|
|
645
|
-
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens, payable(USER), 25);
|
|
645
|
+
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens, payable(USER), 25, USER);
|
|
646
646
|
uint256 failReceived = TOKEN.balanceOf(USER) - tokenBalBefore;
|
|
647
647
|
|
|
648
648
|
// Failed-fee borrower should receive more tokens.
|
|
@@ -699,7 +699,7 @@ contract REVLoansFeeRecovery is TestBaseWorkflow {
|
|
|
699
699
|
REVLoanSource memory source = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: jbMultiTerminal()});
|
|
700
700
|
|
|
701
701
|
vm.prank(borrower);
|
|
702
|
-
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens, payable(borrower), 25);
|
|
702
|
+
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens, payable(borrower), 25, borrower);
|
|
703
703
|
}
|
|
704
704
|
|
|
705
705
|
// After 3 borrows with fee failures, no ETH should be stuck.
|
|
@@ -737,7 +737,7 @@ contract REVLoansFeeRecovery is TestBaseWorkflow {
|
|
|
737
737
|
|
|
738
738
|
uint256 balanceBefore = borrower.balance;
|
|
739
739
|
vm.prank(borrower);
|
|
740
|
-
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens, payable(borrower), 25);
|
|
740
|
+
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokens, payable(borrower), 25, borrower);
|
|
741
741
|
uint256 received = borrower.balance - balanceBefore;
|
|
742
742
|
|
|
743
743
|
// The borrower should always receive something.
|
|
@@ -207,7 +207,6 @@ contract REVLoansFindings 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 REVLoansFindings 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}(
|
|
@@ -372,7 +372,7 @@ contract REVLoansFindings is TestBaseWorkflow {
|
|
|
372
372
|
REVLoanSource memory source = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: jbMultiTerminal()});
|
|
373
373
|
|
|
374
374
|
vm.prank(USER);
|
|
375
|
-
(loanId, loan) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, loanable, tokens, payable(USER), 25);
|
|
375
|
+
(loanId, loan) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, loanable, tokens, payable(USER), 25, USER);
|
|
376
376
|
}
|
|
377
377
|
|
|
378
378
|
//*********************************************************************//
|
|
@@ -411,7 +411,7 @@ contract REVLoansFindings is TestBaseWorkflow {
|
|
|
411
411
|
);
|
|
412
412
|
|
|
413
413
|
vm.prank(USER);
|
|
414
|
-
LOANS_CONTRACT.borrowFrom(REVNET_ID, fakeSource, loanable, tokens, payable(USER), 25);
|
|
414
|
+
LOANS_CONTRACT.borrowFrom(REVNET_ID, fakeSource, loanable, tokens, payable(USER), 25, USER);
|
|
415
415
|
}
|
|
416
416
|
|
|
417
417
|
//*********************************************************************//
|
|
@@ -202,7 +202,6 @@ contract REVLoansRegressions is TestBaseWorkflow {
|
|
|
202
202
|
|
|
203
203
|
LOANS_CONTRACT = new REVLoans({
|
|
204
204
|
controller: jbController(),
|
|
205
|
-
projects: jbProjects(),
|
|
206
205
|
revId: FEE_PROJECT_ID,
|
|
207
206
|
owner: address(this),
|
|
208
207
|
permit2: permit2(),
|
|
@@ -214,7 +213,8 @@ contract REVLoansRegressions is TestBaseWorkflow {
|
|
|
214
213
|
jbDirectory(),
|
|
215
214
|
FEE_PROJECT_ID,
|
|
216
215
|
SUCKER_REGISTRY,
|
|
217
|
-
address(LOANS_CONTRACT)
|
|
216
|
+
address(LOANS_CONTRACT),
|
|
217
|
+
address(0)
|
|
218
218
|
);
|
|
219
219
|
|
|
220
220
|
REV_DEPLOYER = new REVDeployer{salt: REV_DEPLOYER_SALT}(
|
|
@@ -335,7 +335,7 @@ contract REVLoansRegressions is TestBaseWorkflow {
|
|
|
335
335
|
);
|
|
336
336
|
|
|
337
337
|
vm.prank(USER);
|
|
338
|
-
LOANS_CONTRACT.borrowFrom(REVNET_ID, fakeSource, borrowable, tokens, payable(USER), 500);
|
|
338
|
+
LOANS_CONTRACT.borrowFrom(REVNET_ID, fakeSource, borrowable, tokens, payable(USER), 500, USER);
|
|
339
339
|
}
|
|
340
340
|
|
|
341
341
|
/// @notice Verify that the configured loan source (real terminal) is properly registered.
|
|
@@ -229,7 +229,6 @@ contract REVLoansSourceFeeRecovery is TestBaseWorkflow {
|
|
|
229
229
|
|
|
230
230
|
LOANS_CONTRACT = new REVLoans({
|
|
231
231
|
controller: jbController(),
|
|
232
|
-
projects: jbProjects(),
|
|
233
232
|
revId: FEE_PROJECT_ID,
|
|
234
233
|
owner: address(this),
|
|
235
234
|
permit2: permit2(),
|
|
@@ -241,7 +240,8 @@ contract REVLoansSourceFeeRecovery is TestBaseWorkflow {
|
|
|
241
240
|
jbDirectory(),
|
|
242
241
|
FEE_PROJECT_ID,
|
|
243
242
|
SUCKER_REGISTRY,
|
|
244
|
-
address(LOANS_CONTRACT)
|
|
243
|
+
address(LOANS_CONTRACT),
|
|
244
|
+
address(0)
|
|
245
245
|
);
|
|
246
246
|
|
|
247
247
|
REV_DEPLOYER = new REVDeployer{salt: REV_DEPLOYER_SALT}(
|
|
@@ -310,7 +310,7 @@ contract REVLoansSourceFeeRecovery is TestBaseWorkflow {
|
|
|
310
310
|
REVLoanSource memory source = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: jbMultiTerminal()});
|
|
311
311
|
|
|
312
312
|
vm.prank(user);
|
|
313
|
-
(loanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(user), 25);
|
|
313
|
+
(loanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(user), 25, user);
|
|
314
314
|
}
|
|
315
315
|
|
|
316
316
|
// =========================================================================
|
|
@@ -495,7 +495,7 @@ contract REVLoansSourceFeeRecovery is TestBaseWorkflow {
|
|
|
495
495
|
|
|
496
496
|
uint256 balBefore = USER.balance;
|
|
497
497
|
vm.prank(USER);
|
|
498
|
-
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(USER), 25);
|
|
498
|
+
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(USER), 25, USER);
|
|
499
499
|
|
|
500
500
|
uint256 received = USER.balance - balBefore;
|
|
501
501
|
assertGt(received, 0, "Borrower should receive ETH even when source fee terminal fails");
|