@rev-net/core-v6 0.0.39 → 0.0.41
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/package.json +1 -1
- package/src/REVDeployer.sol +53 -54
- package/src/REVHiddenTokens.sol +1 -1
- package/src/REVLoans.sol +141 -150
- package/src/REVOwner.sol +48 -39
- package/src/interfaces/IREVDeployer.sol +10 -10
- package/src/interfaces/IREVHiddenTokens.sol +4 -4
- package/src/interfaces/IREVLoans.sol +28 -28
- package/src/structs/REV721TiersHookFlags.sol +4 -5
- package/src/structs/REVAutoIssuance.sol +4 -2
- package/src/structs/REVConfig.sol +8 -5
- package/src/structs/REVCroptopAllowedPost.sol +7 -8
- package/src/structs/REVDeploy721TiersHookConfig.sol +10 -10
- package/src/structs/REVDescription.sol +6 -5
- package/src/structs/REVLoan.sol +9 -5
- package/src/structs/REVLoanSource.sol +2 -2
- package/src/structs/REVStageConfig.sol +14 -16
- package/src/structs/REVSuckerDeploymentConfig.sol +2 -2
package/src/REVLoans.sol
CHANGED
|
@@ -35,18 +35,15 @@ import {IREVOwner} from "./interfaces/IREVOwner.sol";
|
|
|
35
35
|
import {REVLoan} from "./structs/REVLoan.sol";
|
|
36
36
|
import {REVLoanSource} from "./structs/REVLoanSource.sol";
|
|
37
37
|
|
|
38
|
-
/// @notice
|
|
39
|
-
///
|
|
40
|
-
/// structure orderly.
|
|
41
|
-
/// @dev
|
|
42
|
-
///
|
|
43
|
-
///
|
|
44
|
-
///
|
|
45
|
-
///
|
|
46
|
-
///
|
|
47
|
-
/// After the prepaid duration, the loan will increasingly cost more to pay off. After 10 years, the loan collateral
|
|
48
|
-
/// cannot be
|
|
49
|
-
/// recouped.
|
|
38
|
+
/// @notice Allows revnet token holders to borrow against their tokens instead of cashing out. The borrowable amount
|
|
39
|
+
/// equals what a cash-out would return. Collateral tokens are burned on borrow and re-minted on repayment, keeping the
|
|
40
|
+
/// revnet's token structure orderly. Each loan is represented as an ERC-721 NFT that can be transferred.
|
|
41
|
+
/// @dev Fee structure: an upfront fee is taken at borrow time. 2.5% goes to the source revnet
|
|
42
|
+
/// (MIN_PREPAID_FEE_PERCENT), 1% goes to the $REV revnet (REV_PREPAID_FEE_PERCENT), and a variable amount chosen by the
|
|
43
|
+
/// borrower determines the
|
|
44
|
+
/// prepaid duration — the more paid upfront, the longer the borrower can hold without additional cost. After the
|
|
45
|
+
/// prepaid duration expires, the repayment cost increases linearly until the loan liquidates at 10 years
|
|
46
|
+
/// (LOAN_LIQUIDATION_DURATION), at which point the collateral is permanently lost.
|
|
50
47
|
/// @dev The loaned amounts include the fees taken, meaning the amount paid back is the amount borrowed plus the fees.
|
|
51
48
|
contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans {
|
|
52
49
|
// A library that parses the packed ruleset metadata into a friendlier format.
|
|
@@ -82,20 +79,18 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
82
79
|
// ------------------------- public constants ------------------------ //
|
|
83
80
|
//*********************************************************************//
|
|
84
81
|
|
|
85
|
-
/// @
|
|
86
|
-
///
|
|
87
|
-
///
|
|
88
|
-
/// whereas paying 0% of the loan upfront will cost 100% of the loan amount to be paid off after 10 years. After 10
|
|
89
|
-
/// years with repayment, both loans cost 100% and are liquidated.
|
|
82
|
+
/// @notice The duration after which an unrepaid loan expires and its collateral is permanently lost (10 years).
|
|
83
|
+
/// @dev After the prepaid duration, the loan will cost more to pay off. Paying 50% upfront covers access to the
|
|
84
|
+
/// remaining 50% for 10 years. Paying 0% upfront costs 100% after 10 years. Both loans liquidate at 10 years.
|
|
90
85
|
uint256 public constant override LOAN_LIQUIDATION_DURATION = 3650 days;
|
|
91
86
|
|
|
92
|
-
/// @
|
|
87
|
+
/// @notice The maximum fee percent that can be prepaid when borrowing (50%), in terms of JBConstants.MAX_FEE.
|
|
93
88
|
uint256 public constant override MAX_PREPAID_FEE_PERCENT = 500;
|
|
94
89
|
|
|
95
|
-
/// @
|
|
90
|
+
/// @notice The fee percent charged by the $REV revnet on each loan (1%), in terms of JBConstants.MAX_FEE.
|
|
96
91
|
uint256 public constant override REV_PREPAID_FEE_PERCENT = 10; // 1%
|
|
97
92
|
|
|
98
|
-
/// @
|
|
93
|
+
/// @notice The minimum fee percent that must be prepaid when borrowing (2.5%), in terms of JBConstants.MAX_FEE.
|
|
99
94
|
uint256 public constant override MIN_PREPAID_FEE_PERCENT = 25; // 2.5%
|
|
100
95
|
|
|
101
96
|
//*********************************************************************//
|
|
@@ -110,7 +105,7 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
110
105
|
// --------------- public immutable stored properties ---------------- //
|
|
111
106
|
//*********************************************************************//
|
|
112
107
|
|
|
113
|
-
/// @notice The
|
|
108
|
+
/// @notice The Permit2 contract used for token approvals and transfers.
|
|
114
109
|
IPermit2 public immutable override PERMIT2;
|
|
115
110
|
|
|
116
111
|
/// @notice The controller of revnets that use this loans contract.
|
|
@@ -134,9 +129,9 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
134
129
|
|
|
135
130
|
/// @notice An indication if a revnet currently has outstanding loans from the specified terminal in the specified
|
|
136
131
|
/// token.
|
|
137
|
-
/// @custom:param revnetId The ID of the revnet
|
|
138
|
-
/// @custom:param terminal The terminal
|
|
139
|
-
/// @custom:param token The token
|
|
132
|
+
/// @custom:param revnetId The ID of the revnet to check.
|
|
133
|
+
/// @custom:param terminal The terminal to check.
|
|
134
|
+
/// @custom:param token The token to check.
|
|
140
135
|
mapping(uint256 revnetId => mapping(IJBPayoutTerminal terminal => mapping(address token => bool)))
|
|
141
136
|
public
|
|
142
137
|
override isLoanSourceOf;
|
|
@@ -145,22 +140,22 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
145
140
|
/// @dev This counter only increments (on borrow, repay-with-new-loan, and reallocation) and never decrements.
|
|
146
141
|
/// It does NOT represent the number of currently active loans. Repaid and liquidated loans leave permanent gaps
|
|
147
142
|
/// in the ID sequence. Integrators should not use this to count active loans.
|
|
148
|
-
/// @custom:param revnetId The ID of the revnet to
|
|
143
|
+
/// @custom:param revnetId The ID of the revnet to check.
|
|
149
144
|
mapping(uint256 revnetId => uint256) public override totalLoansBorrowedFor;
|
|
150
145
|
|
|
151
146
|
/// @notice The contract resolving each project ID to its ERC721 URI.
|
|
152
147
|
IJBTokenUriResolver public override tokenUriResolver;
|
|
153
148
|
|
|
154
149
|
/// @notice The total amount loaned out by a revnet from a specified terminal in a specified token.
|
|
155
|
-
/// @custom:param revnetId The ID of the revnet
|
|
156
|
-
/// @custom:param terminal The terminal
|
|
157
|
-
/// @custom:param token The token
|
|
150
|
+
/// @custom:param revnetId The ID of the revnet to check.
|
|
151
|
+
/// @custom:param terminal The terminal to check.
|
|
152
|
+
/// @custom:param token The token to check.
|
|
158
153
|
mapping(uint256 revnetId => mapping(IJBPayoutTerminal terminal => mapping(address token => uint256)))
|
|
159
154
|
public
|
|
160
155
|
override totalBorrowedFrom;
|
|
161
156
|
|
|
162
157
|
/// @notice The total amount of collateral supporting a revnet's loans.
|
|
163
|
-
/// @custom:param revnetId The ID of the revnet
|
|
158
|
+
/// @custom:param revnetId The ID of the revnet to check.
|
|
164
159
|
mapping(uint256 revnetId => uint256) public override totalCollateralOf;
|
|
165
160
|
|
|
166
161
|
//*********************************************************************//
|
|
@@ -172,7 +167,7 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
172
167
|
/// borrowing, but are never removed. The `isLoanSourceOf` mapping tracks whether a source has been registered.
|
|
173
168
|
/// Since the number of distinct (terminal, token) pairs per revnet is practically bounded (typically < 10),
|
|
174
169
|
/// the gas cost of iterating this array in `loanSourcesOf` remains manageable.
|
|
175
|
-
/// @custom:member revnetId The ID of the revnet
|
|
170
|
+
/// @custom:member revnetId The ID of the revnet to look up.
|
|
176
171
|
mapping(uint256 revnetId => REVLoanSource[]) internal _loanSourcesOf;
|
|
177
172
|
|
|
178
173
|
/// @notice The loans.
|
|
@@ -215,10 +210,10 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
215
210
|
//*********************************************************************//
|
|
216
211
|
|
|
217
212
|
/// @notice The amount that can be borrowed from a revnet.
|
|
218
|
-
/// @param revnetId The ID of the revnet to
|
|
219
|
-
/// @param collateralCount The amount of collateral
|
|
220
|
-
/// @param decimals The decimals the resulting fixed point value
|
|
221
|
-
/// @param currency The currency
|
|
213
|
+
/// @param revnetId The ID of the revnet to borrow from.
|
|
214
|
+
/// @param collateralCount The amount of collateral to secure the loan with.
|
|
215
|
+
/// @param decimals The decimals to use for the resulting fixed point value.
|
|
216
|
+
/// @param currency The currency to denominate the resulting amount in.
|
|
222
217
|
/// @return borrowableAmount The amount that can be borrowed from the revnet.
|
|
223
218
|
function borrowableAmountFrom(
|
|
224
219
|
uint256 revnetId,
|
|
@@ -246,8 +241,8 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
246
241
|
});
|
|
247
242
|
}
|
|
248
243
|
|
|
249
|
-
/// @notice Get a loan.
|
|
250
|
-
/// @
|
|
244
|
+
/// @notice Get a loan's full details -- amount, collateral, creation time, prepaid fee, and source.
|
|
245
|
+
/// @param loanId The ID of the loan to look up.
|
|
251
246
|
function loanOf(uint256 loanId) external view override returns (REVLoan memory) {
|
|
252
247
|
return _loanOf[loanId];
|
|
253
248
|
}
|
|
@@ -255,7 +250,7 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
255
250
|
/// @notice The sources of each revnet's loan.
|
|
256
251
|
/// @dev This array only grows -- sources are never removed. The number of distinct sources is practically bounded
|
|
257
252
|
/// by the number of unique (terminal, token) pairs used for borrowing, which is typically small.
|
|
258
|
-
/// @
|
|
253
|
+
/// @param revnetId The ID of the revnet to look up.
|
|
259
254
|
function loanSourcesOf(uint256 revnetId) external view override returns (REVLoanSource[] memory) {
|
|
260
255
|
return _loanSourcesOf[revnetId];
|
|
261
256
|
}
|
|
@@ -264,24 +259,24 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
264
259
|
// -------------------------- public views --------------------------- //
|
|
265
260
|
//*********************************************************************//
|
|
266
261
|
|
|
267
|
-
/// @notice Determines the source fee amount for a loan
|
|
268
|
-
/// @param loan The loan
|
|
269
|
-
/// @param amount The amount
|
|
262
|
+
/// @notice Determines the source fee amount for a loan when paying off a certain amount.
|
|
263
|
+
/// @param loan The loan to determine the source fee for.
|
|
264
|
+
/// @param amount The amount to pay off.
|
|
270
265
|
/// @return sourceFeeAmount The source fee amount for the loan.
|
|
271
266
|
function determineSourceFeeAmount(REVLoan memory loan, uint256 amount) public view returns (uint256) {
|
|
272
267
|
return _determineSourceFeeAmount({loan: loan, amount: amount});
|
|
273
268
|
}
|
|
274
269
|
|
|
275
|
-
/// @notice The revnet ID for
|
|
276
|
-
/// @param loanId The loan ID
|
|
270
|
+
/// @notice The revnet ID for a given loan ID.
|
|
271
|
+
/// @param loanId The loan ID to look up.
|
|
277
272
|
/// @return The ID of the revnet.
|
|
278
273
|
function revnetIdOfLoanWith(uint256 loanId) public pure override returns (uint256) {
|
|
279
274
|
return loanId / _ONE_TRILLION;
|
|
280
275
|
}
|
|
281
276
|
|
|
282
277
|
/// @notice Returns the URI where the ERC-721 standard JSON of a loan is hosted.
|
|
283
|
-
/// @param loanId The ID of the loan to get
|
|
284
|
-
/// @return The token URI
|
|
278
|
+
/// @param loanId The ID of the loan to get the URI for.
|
|
279
|
+
/// @return The token URI for the provided `loanId`.
|
|
285
280
|
function tokenURI(uint256 loanId) public view override returns (string memory) {
|
|
286
281
|
// Keep a reference to the resolver.
|
|
287
282
|
IJBTokenUriResolver resolver = tokenUriResolver;
|
|
@@ -298,7 +293,7 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
298
293
|
//*********************************************************************//
|
|
299
294
|
|
|
300
295
|
/// @notice Checks this contract's balance of a specific token.
|
|
301
|
-
/// @param token The address of the token to
|
|
296
|
+
/// @param token The address of the token to check.
|
|
302
297
|
/// @return This contract's balance.
|
|
303
298
|
function _balanceOf(address token) internal view returns (uint256) {
|
|
304
299
|
// If the `token` is native, get the native token balance.
|
|
@@ -328,11 +323,11 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
328
323
|
/// effective collateralization margin. For example, a 20% `cashOutTaxRate` means borrowers can only extract ~80%
|
|
329
324
|
/// of their pro-rata surplus, providing a ~20% buffer against collateral depreciation before liquidation.
|
|
330
325
|
/// A `cashOutTaxRate` of 0 means the full pro-rata amount is borrowable (true 100% LTV with no margin).
|
|
331
|
-
/// @param revnetId The ID of the revnet to
|
|
332
|
-
/// @param collateralCount The amount of collateral
|
|
333
|
-
/// @param decimals The decimals the resulting fixed point value
|
|
334
|
-
/// @param currency The currency
|
|
335
|
-
/// @param terminals The terminals
|
|
326
|
+
/// @param revnetId The ID of the revnet to borrow from.
|
|
327
|
+
/// @param collateralCount The amount of collateral to secure the loan with.
|
|
328
|
+
/// @param decimals The decimals to use for the resulting fixed point value.
|
|
329
|
+
/// @param currency The currency to denominate the resulting amount in.
|
|
330
|
+
/// @param terminals The terminals to borrow from.
|
|
336
331
|
/// @param currentStage The pre-fetched current ruleset.
|
|
337
332
|
/// @return borrowableAmount The amount that can be borrowed from the revnet.
|
|
338
333
|
function _borrowableAmountFrom(
|
|
@@ -389,11 +384,11 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
389
384
|
}
|
|
390
385
|
|
|
391
386
|
/// @notice The amount of the loan that should be borrowed for the given collateral amount.
|
|
392
|
-
/// @param loan The loan
|
|
393
|
-
/// @param revnetId The ID of the revnet to
|
|
394
|
-
/// @param collateralCount The amount of collateral
|
|
387
|
+
/// @param loan The loan to determine the borrow amount for.
|
|
388
|
+
/// @param revnetId The ID of the revnet to borrow from.
|
|
389
|
+
/// @param collateralCount The amount of collateral to secure the loan with.
|
|
395
390
|
/// @param currentRuleset The pre-fetched current ruleset.
|
|
396
|
-
/// @return borrowAmount The amount
|
|
391
|
+
/// @return borrowAmount The amount that should be borrowed.
|
|
397
392
|
function _borrowAmountFrom(
|
|
398
393
|
REVLoan storage loan,
|
|
399
394
|
uint256 revnetId,
|
|
@@ -452,9 +447,9 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
452
447
|
(currentRuleset,) = CONTROLLER.currentRulesetOf(revnetId);
|
|
453
448
|
}
|
|
454
449
|
|
|
455
|
-
/// @notice Determines the source fee amount for a loan
|
|
456
|
-
/// @param loan The loan
|
|
457
|
-
/// @param amount The amount
|
|
450
|
+
/// @notice Determines the source fee amount for a loan when paying off a certain amount.
|
|
451
|
+
/// @param loan The loan to determine the source fee for.
|
|
452
|
+
/// @param amount The amount to pay off.
|
|
458
453
|
/// @return The source fee amount for the loan.
|
|
459
454
|
function _determineSourceFeeAmount(REVLoan memory loan, uint256 amount) internal view returns (uint256) {
|
|
460
455
|
// Keep a reference to the time since the loan was created.
|
|
@@ -489,12 +484,12 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
489
484
|
return mulDiv({x: fullSourceFeeAmount, y: amount, denominator: loan.amount});
|
|
490
485
|
}
|
|
491
486
|
|
|
492
|
-
/// @notice Generate
|
|
487
|
+
/// @notice Generate an ID for a loan given a revnet ID and a loan number within that revnet.
|
|
493
488
|
/// @dev The multiplication and addition can theoretically overflow a uint256 if revnetId or loanNumber are
|
|
494
489
|
/// astronomically large. In practice this is infeasible — it would require 2^256 loans or project IDs, far
|
|
495
490
|
/// beyond any realistic usage. No overflow check is needed.
|
|
496
491
|
/// @param revnetId The ID of the revnet to generate a loan ID for.
|
|
497
|
-
/// @param loanNumber The loan number
|
|
492
|
+
/// @param loanNumber The loan number within the revnet.
|
|
498
493
|
/// @return The token ID of the 721.
|
|
499
494
|
function _generateLoanId(uint256 revnetId, uint256 loanNumber) internal pure returns (uint256) {
|
|
500
495
|
return (revnetId * _ONE_TRILLION) + loanNumber;
|
|
@@ -525,9 +520,9 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
525
520
|
/// arithmetic errors. For cross-currency sources, the normalized amount is then converted via the price feed.
|
|
526
521
|
/// @dev Inverse price feeds may truncate to zero at low decimal counts (e.g. a feed returning 1e21 at 6 decimals
|
|
527
522
|
/// inverts to mulDiv(1e6, 1e6, 1e21) = 0). Sources with a zero price are skipped to prevent division-by-zero.
|
|
528
|
-
/// @param revnetId The ID of the revnet to check
|
|
529
|
-
/// @param decimals The decimals the resulting fixed point value
|
|
530
|
-
/// @param currency The currency the resulting value
|
|
523
|
+
/// @param revnetId The ID of the revnet to check.
|
|
524
|
+
/// @param decimals The decimals to use for the resulting fixed point value.
|
|
525
|
+
/// @param currency The currency to denominate the resulting value in.
|
|
531
526
|
/// @return borrowedAmount The total amount borrowed.
|
|
532
527
|
function _totalBorrowedFrom(
|
|
533
528
|
uint256 revnetId,
|
|
@@ -604,16 +599,15 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
604
599
|
/// lost and cannot be recovered.
|
|
605
600
|
/// @dev A delegated operator (with OPEN_LOAN permission) can set `beneficiary` to any address, directing borrowed
|
|
606
601
|
/// funds away from the holder. Holders should only grant OPEN_LOAN to fully trusted operators.
|
|
607
|
-
/// @param revnetId The ID of the revnet
|
|
608
|
-
/// @param source The source of the loan
|
|
609
|
-
/// @param minBorrowAmount The minimum amount
|
|
602
|
+
/// @param revnetId The ID of the revnet to borrow from.
|
|
603
|
+
/// @param source The source of the loan (terminal and token).
|
|
604
|
+
/// @param minBorrowAmount The minimum amount to borrow, denominated in the token of the source's accounting
|
|
610
605
|
/// context.
|
|
611
606
|
/// @param collateralCount The amount of tokens to use as collateral for the loan.
|
|
612
|
-
/// @param beneficiary The address that
|
|
613
|
-
/// @param prepaidFeePercent The fee percent
|
|
614
|
-
///
|
|
615
|
-
/// @return
|
|
616
|
-
/// @return loan The loan created from borrowing.
|
|
607
|
+
/// @param beneficiary The address that will receive the borrowed funds and the tokens resulting from fee payments.
|
|
608
|
+
/// @param prepaidFeePercent The fee percent to charge upfront. Prepaying a fee is cheaper than paying later.
|
|
609
|
+
/// @return loanId The ID of the loan created.
|
|
610
|
+
/// @return loan The loan created.
|
|
617
611
|
function borrowFrom(
|
|
618
612
|
uint256 revnetId,
|
|
619
613
|
REVLoanSource calldata source,
|
|
@@ -642,7 +636,7 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
642
636
|
});
|
|
643
637
|
}
|
|
644
638
|
|
|
645
|
-
/// @notice
|
|
639
|
+
/// @notice Liquidate loans that have exceeded the 10-year liquidation duration.
|
|
646
640
|
/// @dev Liquidation permanently destroys the collateral backing expired loans. Since collateral tokens were burned
|
|
647
641
|
/// at deposit time (not held in escrow), there is nothing to return upon liquidation -- the collateral count is
|
|
648
642
|
/// simply removed from tracking. The borrower retains whatever funds they received from the loan, but the
|
|
@@ -653,8 +647,8 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
653
647
|
/// @dev Since some loans may be reallocated or paid off, loans within startingLoanId and startingLoanId + count
|
|
654
648
|
/// may be skipped, so choose these parameters carefully to avoid extra gas usage.
|
|
655
649
|
/// @param revnetId The ID of the revnet to liquidate loans from.
|
|
656
|
-
/// @param startingLoanId The
|
|
657
|
-
/// @param count The
|
|
650
|
+
/// @param startingLoanId The loan number to start iterating from.
|
|
651
|
+
/// @param count The number of loans to iterate over.
|
|
658
652
|
function liquidateExpiredLoansFrom(uint256 revnetId, uint256 startingLoanId, uint256 count) external override {
|
|
659
653
|
// Prevent cross-revnet accounting corruption: loan numbers must stay within the revnet's ID namespace.
|
|
660
654
|
if (startingLoanId + count > _ONE_TRILLION) revert REVLoans_LoanIdOverflow();
|
|
@@ -702,7 +696,7 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
702
696
|
}
|
|
703
697
|
}
|
|
704
698
|
|
|
705
|
-
/// @notice
|
|
699
|
+
/// @notice Refinance a loan by transferring extra collateral from an existing loan to a new loan.
|
|
706
700
|
/// @dev Useful if a loan's collateral has gone up in value since the loan was created.
|
|
707
701
|
/// @dev Refinancing a loan will burn the original and create two new loans.
|
|
708
702
|
/// @dev This function is intentionally not payable — it only moves existing collateral between loans and does
|
|
@@ -711,15 +705,15 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
711
705
|
/// borrowed funds from the new loan away from the loan owner. Grant this permission only to trusted operators.
|
|
712
706
|
/// @param loanId The ID of the loan to reallocate collateral from.
|
|
713
707
|
/// @param collateralCountToTransfer The amount of collateral to transfer from the original loan.
|
|
714
|
-
/// @param source The source of the loan
|
|
715
|
-
/// @param minBorrowAmount The minimum amount
|
|
708
|
+
/// @param source The source of the new loan (terminal and token). Must match the existing loan's source.
|
|
709
|
+
/// @param minBorrowAmount The minimum amount to borrow, denominated in the token of the source's accounting
|
|
716
710
|
/// context.
|
|
717
|
-
/// @param collateralCountToAdd The amount of collateral to add to the loan.
|
|
718
|
-
/// @param beneficiary The address that
|
|
719
|
-
/// @param prepaidFeePercent The fee percent
|
|
720
|
-
/// @return reallocatedLoanId The ID of the
|
|
711
|
+
/// @param collateralCountToAdd The amount of collateral to add to the new loan from your balance.
|
|
712
|
+
/// @param beneficiary The address that will receive the borrowed funds and the tokens resulting from fee payments.
|
|
713
|
+
/// @param prepaidFeePercent The fee percent to charge upfront for the new loan.
|
|
714
|
+
/// @return reallocatedLoanId The ID of the reallocated (reduced) loan.
|
|
721
715
|
/// @return newLoanId The ID of the new loan.
|
|
722
|
-
/// @return reallocatedLoan The loan
|
|
716
|
+
/// @return reallocatedLoan The reallocated loan data.
|
|
723
717
|
/// @return newLoan The new loan created from reallocating collateral.
|
|
724
718
|
function reallocateCollateralFromLoan(
|
|
725
719
|
uint256 loanId,
|
|
@@ -777,18 +771,17 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
777
771
|
});
|
|
778
772
|
}
|
|
779
773
|
|
|
780
|
-
/// @notice
|
|
781
|
-
/// the loan.
|
|
774
|
+
/// @notice Repay a loan or return excess collateral no longer needed to support the loan.
|
|
782
775
|
/// @dev A delegated operator (with REPAY_LOAN permission) can set `beneficiary` to any address, directing returned
|
|
783
776
|
/// collateral tokens away from the loan owner. Grant this permission only to trusted operators.
|
|
784
|
-
/// @param loanId The ID of the loan
|
|
785
|
-
/// @param maxRepayBorrowAmount The maximum amount
|
|
777
|
+
/// @param loanId The ID of the loan to repay.
|
|
778
|
+
/// @param maxRepayBorrowAmount The maximum amount to repay, denominated in the token of the source's
|
|
786
779
|
/// accounting context.
|
|
787
|
-
/// @param collateralCountToReturn The amount of collateral
|
|
788
|
-
/// @param beneficiary The address
|
|
789
|
-
/// @param allowance An allowance to
|
|
790
|
-
/// @return paidOffLoanId The ID of the loan after
|
|
791
|
-
/// @return paidOffloan The loan after
|
|
780
|
+
/// @param collateralCountToReturn The amount of collateral to return from the loan.
|
|
781
|
+
/// @param beneficiary The address to receive the returned collateral and any tokens resulting from paying fees.
|
|
782
|
+
/// @param allowance An allowance to facilitate permit2 interactions.
|
|
783
|
+
/// @return paidOffLoanId The ID of the loan after repayment.
|
|
784
|
+
/// @return paidOffloan The loan after repayment.
|
|
792
785
|
function repayLoan(
|
|
793
786
|
uint256 loanId,
|
|
794
787
|
uint256 maxRepayBorrowAmount,
|
|
@@ -894,7 +887,7 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
894
887
|
}
|
|
895
888
|
}
|
|
896
889
|
|
|
897
|
-
/// @notice
|
|
890
|
+
/// @notice Set the address of the resolver used to retrieve the tokenURI of loans.
|
|
898
891
|
/// @param resolver The address of the new resolver.
|
|
899
892
|
function setTokenUriResolver(IJBTokenUriResolver resolver) external override onlyOwner {
|
|
900
893
|
// Store the new resolver.
|
|
@@ -907,11 +900,11 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
907
900
|
// --------------------- internal transactions ----------------------- //
|
|
908
901
|
//*********************************************************************//
|
|
909
902
|
|
|
910
|
-
/// @notice
|
|
911
|
-
/// @param token The token
|
|
912
|
-
/// @param amount The number of tokens
|
|
903
|
+
/// @notice Accept an incoming token.
|
|
904
|
+
/// @param token The token to accept.
|
|
905
|
+
/// @param amount The number of tokens to accept.
|
|
913
906
|
/// @param allowance The permit2 context.
|
|
914
|
-
/// @return amount The number of tokens
|
|
907
|
+
/// @return amount The number of tokens accepted.
|
|
915
908
|
function _acceptFundsFor(
|
|
916
909
|
address token,
|
|
917
910
|
uint256 amount,
|
|
@@ -957,11 +950,11 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
957
950
|
return _balanceOf(token) - balanceBefore;
|
|
958
951
|
}
|
|
959
952
|
|
|
960
|
-
/// @notice
|
|
953
|
+
/// @notice Add collateral to a loan by burning the collateral tokens permanently.
|
|
961
954
|
/// @dev The collateral tokens are burned via the controller, not held in escrow. They are only re-minted if the
|
|
962
955
|
/// loan is repaid. If the loan expires and is liquidated, the burned collateral is permanently lost.
|
|
963
|
-
/// @param revnetId The ID of the revnet
|
|
964
|
-
/// @param amount The
|
|
956
|
+
/// @param revnetId The ID of the revnet to add collateral in.
|
|
957
|
+
/// @param amount The amount of collateral to add to the loan.
|
|
965
958
|
function _addCollateralTo(uint256 revnetId, uint256 amount, address holder) internal {
|
|
966
959
|
// Increment the total amount of collateral tokens.
|
|
967
960
|
totalCollateralOf[revnetId] += amount;
|
|
@@ -971,12 +964,12 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
971
964
|
}
|
|
972
965
|
|
|
973
966
|
/// @notice Add a new amount to the loan that is greater than the previous amount.
|
|
974
|
-
/// @param loan The loan
|
|
975
|
-
/// @param revnetId The ID of the revnet the loan is
|
|
976
|
-
/// @param addedBorrowAmount The amount
|
|
967
|
+
/// @param loan The loan to add to.
|
|
968
|
+
/// @param revnetId The ID of the revnet the loan is in.
|
|
969
|
+
/// @param addedBorrowAmount The amount to add to the loan, denominated in the token of the source's
|
|
977
970
|
/// accounting context.
|
|
978
|
-
/// @param sourceFeeAmount The
|
|
979
|
-
/// @param beneficiary The address
|
|
971
|
+
/// @param sourceFeeAmount The fee amount taken from the revnet acting as the source of the loan.
|
|
972
|
+
/// @param beneficiary The address to receive the borrowed funds and any tokens resulting from paying fees.
|
|
980
973
|
function _addTo(
|
|
981
974
|
REVLoan memory loan,
|
|
982
975
|
uint256 revnetId,
|
|
@@ -1053,21 +1046,20 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
1053
1046
|
});
|
|
1054
1047
|
}
|
|
1055
1048
|
|
|
1056
|
-
/// @notice
|
|
1057
|
-
/// to support the loan.
|
|
1049
|
+
/// @notice Adjust a loan -- pay it back, add more, or return excess collateral.
|
|
1058
1050
|
/// @dev CEI ordering note: `totalCollateralOf` is not incremented until `_addCollateralTo` executes,
|
|
1059
1051
|
/// which happens after the external calls in `_addTo` (useAllowanceOf, fee payment, transfer). A reentrant
|
|
1060
1052
|
/// `borrowFrom` during those calls would see a lower `totalCollateralOf`, potentially passing collateral
|
|
1061
1053
|
/// checks that should fail. Practically infeasible — requires an adversarial pay hook on the revnet's own
|
|
1062
1054
|
/// terminal that calls back into `borrowFrom`, which is not a realistic deployment configuration.
|
|
1063
|
-
/// @param loan The loan
|
|
1064
|
-
/// @param revnetId The ID of the revnet the loan is
|
|
1055
|
+
/// @param loan The loan to adjust.
|
|
1056
|
+
/// @param revnetId The ID of the revnet the loan is in.
|
|
1065
1057
|
/// @param newBorrowAmount The new amount of the loan, denominated in the token of the source's accounting
|
|
1066
1058
|
/// context.
|
|
1067
|
-
/// @param newCollateralCount The new amount of collateral
|
|
1068
|
-
/// @param sourceFeeAmount The
|
|
1069
|
-
/// @param beneficiary The address
|
|
1070
|
-
/// @param holder The address whose tokens
|
|
1059
|
+
/// @param newCollateralCount The new amount of collateral to back the loan with.
|
|
1060
|
+
/// @param sourceFeeAmount The fee amount taken from the revnet acting as the source of the loan.
|
|
1061
|
+
/// @param beneficiary The address to receive the returned collateral and any tokens resulting from paying fees.
|
|
1062
|
+
/// @param holder The address whose tokens to use as collateral (burned).
|
|
1071
1063
|
function _adjust(
|
|
1072
1064
|
REVLoan storage loan,
|
|
1073
1065
|
uint256 revnetId,
|
|
@@ -1142,12 +1134,12 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
1142
1134
|
}
|
|
1143
1135
|
}
|
|
1144
1136
|
|
|
1145
|
-
/// @notice Logic to
|
|
1146
|
-
/// @param to The address
|
|
1147
|
-
/// @param token The token
|
|
1148
|
-
/// @param amount The number of tokens
|
|
1137
|
+
/// @notice Logic to trigger before transferring tokens from this contract.
|
|
1138
|
+
/// @param to The address to transfer to.
|
|
1139
|
+
/// @param token The token to transfer.
|
|
1140
|
+
/// @param amount The number of tokens to transfer, as a fixed point number with the same number of decimals
|
|
1149
1141
|
/// as the token specifies.
|
|
1150
|
-
/// @return payValue The value to attach to the transaction
|
|
1142
|
+
/// @return payValue The value to attach to the transaction.
|
|
1151
1143
|
function _beforeTransferTo(address to, address token, uint256 amount) internal returns (uint256) {
|
|
1152
1144
|
// If the token is the native token, no allowance needed.
|
|
1153
1145
|
if (token == JBConstants.NATIVE_TOKEN) return amount;
|
|
@@ -1155,9 +1147,9 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
1155
1147
|
return 0;
|
|
1156
1148
|
}
|
|
1157
1149
|
|
|
1158
|
-
/// @notice
|
|
1150
|
+
/// @notice Clear any token allowance granted by `_beforeTransferTo`.
|
|
1159
1151
|
/// @param to The address that was granted the allowance.
|
|
1160
|
-
/// @param token The token whose allowance
|
|
1152
|
+
/// @param token The token whose allowance to clear.
|
|
1161
1153
|
function _afterTransferTo(address to, address token) internal {
|
|
1162
1154
|
if (token == JBConstants.NATIVE_TOKEN) return;
|
|
1163
1155
|
IERC20(token).forceApprove({spender: to, value: 0});
|
|
@@ -1166,15 +1158,15 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
1166
1158
|
/// @notice Internal implementation of loan creation, without the OPEN_LOAN permission check.
|
|
1167
1159
|
/// @dev Called by `borrowFrom` (after its own permission check) and by `reallocateCollateralFromLoan`
|
|
1168
1160
|
/// (which only requires REALLOCATE_LOAN permission).
|
|
1169
|
-
/// @param revnetId The ID of the revnet
|
|
1170
|
-
/// @param source The source of the loan
|
|
1171
|
-
/// @param minBorrowAmount The minimum amount
|
|
1161
|
+
/// @param revnetId The ID of the revnet to borrow from.
|
|
1162
|
+
/// @param source The source of the loan (terminal and token).
|
|
1163
|
+
/// @param minBorrowAmount The minimum amount to borrow.
|
|
1172
1164
|
/// @param collateralCount The amount of tokens to use as collateral for the loan.
|
|
1173
|
-
/// @param beneficiary The address that
|
|
1174
|
-
/// @param prepaidFeePercent The fee percent
|
|
1175
|
-
/// @param holder The address whose tokens
|
|
1176
|
-
/// @return loanId The ID of the loan created
|
|
1177
|
-
/// @return loan The loan created
|
|
1165
|
+
/// @param beneficiary The address that will receive the borrowed funds and fee payment tokens.
|
|
1166
|
+
/// @param prepaidFeePercent The fee percent to charge upfront.
|
|
1167
|
+
/// @param holder The address whose tokens to use as collateral and who receives the loan NFT.
|
|
1168
|
+
/// @return loanId The ID of the loan created.
|
|
1169
|
+
/// @return loan The loan created.
|
|
1178
1170
|
function _borrowFrom(
|
|
1179
1171
|
uint256 revnetId,
|
|
1180
1172
|
REVLoanSource calldata source,
|
|
@@ -1278,11 +1270,11 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
1278
1270
|
return (loanId, loan);
|
|
1279
1271
|
}
|
|
1280
1272
|
|
|
1281
|
-
/// @notice
|
|
1273
|
+
/// @notice Reallocate collateral from a loan by making a new loan based on the original, with reduced collateral.
|
|
1282
1274
|
/// @param loanId The ID of the loan to reallocate collateral from.
|
|
1283
1275
|
/// @param revnetId The ID of the revnet the loan is from.
|
|
1284
1276
|
/// @param collateralCountToRemove The amount of collateral to remove from the loan.
|
|
1285
|
-
/// @return reallocatedLoanId The ID of the loan.
|
|
1277
|
+
/// @return reallocatedLoanId The ID of the reallocated loan.
|
|
1286
1278
|
/// @return reallocatedLoan The reallocated loan.
|
|
1287
1279
|
function _reallocateCollateralFromLoan(
|
|
1288
1280
|
uint256 loanId,
|
|
@@ -1363,10 +1355,10 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
1363
1355
|
});
|
|
1364
1356
|
}
|
|
1365
1357
|
|
|
1366
|
-
/// @notice
|
|
1367
|
-
/// @param loan The loan
|
|
1368
|
-
/// @param revnetId The ID of the revnet the loan is
|
|
1369
|
-
/// @param repaidBorrowAmount The amount
|
|
1358
|
+
/// @notice Pay off a loan.
|
|
1359
|
+
/// @param loan The loan to pay off.
|
|
1360
|
+
/// @param revnetId The ID of the revnet the loan is in.
|
|
1361
|
+
/// @param repaidBorrowAmount The amount to pay off, denominated in the token of the source's accounting
|
|
1370
1362
|
/// context.
|
|
1371
1363
|
function _removeFrom(REVLoan memory loan, uint256 revnetId, uint256 repaidBorrowAmount) internal {
|
|
1372
1364
|
// Decrement the total amount of a token being loaned out by the revnet from its terminal.
|
|
@@ -1391,14 +1383,13 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
1391
1383
|
_afterTransferTo({to: address(loan.source.terminal), token: loan.source.token});
|
|
1392
1384
|
}
|
|
1393
1385
|
|
|
1394
|
-
/// @notice
|
|
1395
|
-
/// @param loanId The ID of the loan
|
|
1396
|
-
/// @param loan The loan
|
|
1397
|
-
/// @param repayBorrowAmount The amount
|
|
1398
|
-
///
|
|
1399
|
-
/// @param
|
|
1400
|
-
/// @param
|
|
1401
|
-
/// @param beneficiary The address receiving the returned collateral and any tokens resulting from paying fees.
|
|
1386
|
+
/// @notice Pay down a loan.
|
|
1387
|
+
/// @param loanId The ID of the loan to pay down.
|
|
1388
|
+
/// @param loan The loan to pay down.
|
|
1389
|
+
/// @param repayBorrowAmount The amount to pay down, denominated in the token of the source's accounting context.
|
|
1390
|
+
/// @param sourceFeeAmount The fee amount taken from the revnet acting as the source of the loan.
|
|
1391
|
+
/// @param collateralCountToReturn The amount of collateral to return that the loan no longer requires.
|
|
1392
|
+
/// @param beneficiary The address to receive the returned collateral and any tokens resulting from paying fees.
|
|
1402
1393
|
/// @param loanOwner The owner of the loan NFT (receives replacement loan if partial repay).
|
|
1403
1394
|
// slither-disable-next-line reentrancy-eth,reentrancy-events
|
|
1404
1395
|
function _repayLoan(
|
|
@@ -1508,10 +1499,10 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
1508
1499
|
}
|
|
1509
1500
|
}
|
|
1510
1501
|
|
|
1511
|
-
/// @notice
|
|
1512
|
-
/// @param revnetId The ID of the revnet the loan is
|
|
1513
|
-
/// @param collateralCount The amount of collateral
|
|
1514
|
-
/// @param beneficiary The address
|
|
1502
|
+
/// @notice Return collateral from a loan.
|
|
1503
|
+
/// @param revnetId The ID of the revnet the loan is in.
|
|
1504
|
+
/// @param collateralCount The amount of collateral to return from the loan.
|
|
1505
|
+
/// @param beneficiary The address to receive the returned collateral.
|
|
1515
1506
|
function _returnCollateralFrom(uint256 revnetId, uint256 collateralCount, address payable beneficiary) internal {
|
|
1516
1507
|
// Decrement the total amount of collateral tokens.
|
|
1517
1508
|
totalCollateralOf[revnetId] -= collateralCount;
|
|
@@ -1527,10 +1518,10 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
1527
1518
|
});
|
|
1528
1519
|
}
|
|
1529
1520
|
|
|
1530
|
-
/// @notice
|
|
1521
|
+
/// @notice Transfer tokens.
|
|
1531
1522
|
/// @param from The address to transfer tokens from.
|
|
1532
1523
|
/// @param to The address to transfer tokens to.
|
|
1533
|
-
/// @param token The address of the token
|
|
1524
|
+
/// @param token The address of the token to transfer.
|
|
1534
1525
|
/// @param amount The amount of tokens to transfer, as a fixed point number with the same number of decimals as the
|
|
1535
1526
|
/// token.
|
|
1536
1527
|
function _transferFrom(address from, address payable to, address token, uint256 amount) internal virtual {
|
|
@@ -1555,13 +1546,13 @@ contract REVLoans is ERC721, ERC2771Context, JBPermissioned, Ownable, IREVLoans
|
|
|
1555
1546
|
PERMIT2.transferFrom({from: from, to: to, amount: uint160(amount), token: token});
|
|
1556
1547
|
}
|
|
1557
1548
|
|
|
1558
|
-
/// @notice
|
|
1549
|
+
/// @notice Attempt to pay a fee to a terminal. On failure, cleans up the ERC-20 allowance and returns false.
|
|
1559
1550
|
/// @param terminal The terminal to pay the fee to.
|
|
1560
|
-
/// @param projectId The project
|
|
1561
|
-
/// @param token The token
|
|
1551
|
+
/// @param projectId The project to pay the fee to.
|
|
1552
|
+
/// @param token The token to pay the fee with.
|
|
1562
1553
|
/// @param amount The fee amount.
|
|
1563
1554
|
/// @param beneficiary The address to credit for the fee payment.
|
|
1564
|
-
/// @param metadataProjectId The project ID
|
|
1555
|
+
/// @param metadataProjectId The project ID to encode in the payment metadata.
|
|
1565
1556
|
/// @return success Whether the fee was successfully paid.
|
|
1566
1557
|
function _tryPayFee(
|
|
1567
1558
|
IJBTerminal terminal,
|