@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
package/src/REVOwner.sol
CHANGED
|
@@ -59,6 +59,9 @@ contract REVOwner is IJBRulesetDataHook, IJBCashOutHook {
|
|
|
59
59
|
/// @notice The Juicebox project ID of the revnet that receives cash out fees.
|
|
60
60
|
uint256 public immutable FEE_REVNET_ID;
|
|
61
61
|
|
|
62
|
+
/// @notice The hidden tokens contract used by all revnets.
|
|
63
|
+
address public immutable HIDDEN_TOKENS;
|
|
64
|
+
|
|
62
65
|
/// @notice The loan contract used by all revnets.
|
|
63
66
|
address public immutable LOANS;
|
|
64
67
|
|
|
@@ -99,12 +102,14 @@ contract REVOwner is IJBRulesetDataHook, IJBCashOutHook {
|
|
|
99
102
|
/// @param feeRevnetId The Juicebox project ID of the fee revnet.
|
|
100
103
|
/// @param suckerRegistry The sucker registry.
|
|
101
104
|
/// @param loans The loan contract address.
|
|
105
|
+
/// @param hiddenTokens The hidden tokens contract address.
|
|
102
106
|
constructor(
|
|
103
107
|
IJBBuybackHookRegistry buybackHook,
|
|
104
108
|
IJBDirectory directory,
|
|
105
109
|
uint256 feeRevnetId,
|
|
106
110
|
IJBSuckerRegistry suckerRegistry,
|
|
107
|
-
address loans
|
|
111
|
+
address loans,
|
|
112
|
+
address hiddenTokens
|
|
108
113
|
) {
|
|
109
114
|
BUYBACK_HOOK = buybackHook;
|
|
110
115
|
DIRECTORY = directory;
|
|
@@ -112,6 +117,8 @@ contract REVOwner is IJBRulesetDataHook, IJBCashOutHook {
|
|
|
112
117
|
SUCKER_REGISTRY = suckerRegistry;
|
|
113
118
|
// slither-disable-next-line missing-zero-check
|
|
114
119
|
LOANS = loans;
|
|
120
|
+
// slither-disable-next-line missing-zero-check
|
|
121
|
+
HIDDEN_TOKENS = hiddenTokens;
|
|
115
122
|
_DEPLOYER_BINDER = msg.sender;
|
|
116
123
|
}
|
|
117
124
|
|
|
@@ -130,7 +137,8 @@ contract REVOwner is IJBRulesetDataHook, IJBCashOutHook {
|
|
|
130
137
|
/// @return cashOutTaxRate The cash out tax rate, which influences the amount of terminal tokens which get cashed
|
|
131
138
|
/// out.
|
|
132
139
|
/// @return cashOutCount The number of revnet tokens that are cashed out.
|
|
133
|
-
/// @return totalSupply The total
|
|
140
|
+
/// @return totalSupply The total token supply across all chains (for both proportional reclaim and tax).
|
|
141
|
+
/// @return effectiveSurplusValue The global surplus across all chains for proportional reclaim.
|
|
134
142
|
/// @return hookSpecifications The amount of funds and the data to send to cash out hooks (this contract).
|
|
135
143
|
function beforeCashOutRecordedWith(JBBeforeCashOutRecordedContext calldata context)
|
|
136
144
|
external
|
|
@@ -140,6 +148,7 @@ contract REVOwner is IJBRulesetDataHook, IJBCashOutHook {
|
|
|
140
148
|
uint256 cashOutTaxRate,
|
|
141
149
|
uint256 cashOutCount,
|
|
142
150
|
uint256 totalSupply,
|
|
151
|
+
uint256 effectiveSurplusValue,
|
|
143
152
|
JBCashOutHookSpecification[] memory hookSpecifications
|
|
144
153
|
)
|
|
145
154
|
{
|
|
@@ -147,7 +156,7 @@ contract REVOwner is IJBRulesetDataHook, IJBCashOutHook {
|
|
|
147
156
|
// This relies on the sucker registry to only contain trusted sucker contracts deployed via
|
|
148
157
|
// the registry's own deploySuckersFor flow — external addresses cannot register as suckers.
|
|
149
158
|
if (_isSuckerOf({revnetId: context.projectId, addr: context.holder})) {
|
|
150
|
-
return (0, context.cashOutCount, context.totalSupply, hookSpecifications);
|
|
159
|
+
return (0, context.cashOutCount, context.totalSupply, context.surplus.value, hookSpecifications);
|
|
151
160
|
}
|
|
152
161
|
|
|
153
162
|
// Keep a reference to the cash out delay of the revnet.
|
|
@@ -161,11 +170,23 @@ contract REVOwner is IJBRulesetDataHook, IJBCashOutHook {
|
|
|
161
170
|
// Get the terminal that will receive the cash out fee.
|
|
162
171
|
IJBTerminal feeTerminal = DIRECTORY.primaryTerminalOf({projectId: FEE_REVNET_ID, token: context.surplus.token});
|
|
163
172
|
|
|
173
|
+
// Compute the cross-chain total supply (local + remote peer chain supplies) for cross-chain-aware bonding
|
|
174
|
+
// curve.
|
|
175
|
+
totalSupply = context.totalSupply + SUCKER_REGISTRY.remoteTotalSupplyOf(context.projectId);
|
|
176
|
+
effectiveSurplusValue = context.surplus.value
|
|
177
|
+
+ SUCKER_REGISTRY.remoteSurplusOf({
|
|
178
|
+
projectId: context.projectId,
|
|
179
|
+
decimals: context.surplus.decimals,
|
|
180
|
+
currency: uint256(uint160(context.surplus.token))
|
|
181
|
+
});
|
|
182
|
+
|
|
164
183
|
// If there's no cash out tax (100% cash out tax rate), if there's no fee terminal, or if the beneficiary is
|
|
165
|
-
// feeless (e.g. the router terminal routing value between projects), proxy
|
|
184
|
+
// feeless (e.g. the router terminal routing value between projects), proxy to the buyback hook with our
|
|
185
|
+
// totalSupply and effectiveSurplusValue.
|
|
166
186
|
if (context.cashOutTaxRate == 0 || address(feeTerminal) == address(0) || context.beneficiaryIsFeeless) {
|
|
167
187
|
// slither-disable-next-line unused-return
|
|
168
|
-
|
|
188
|
+
(cashOutTaxRate, cashOutCount,,, hookSpecifications) = BUYBACK_HOOK.beforeCashOutRecordedWith(context);
|
|
189
|
+
return (cashOutTaxRate, cashOutCount, totalSupply, effectiveSurplusValue, hookSpecifications);
|
|
169
190
|
}
|
|
170
191
|
|
|
171
192
|
// Split the cashed-out tokens into a fee portion and a non-fee portion.
|
|
@@ -178,20 +199,33 @@ contract REVOwner is IJBRulesetDataHook, IJBCashOutHook {
|
|
|
178
199
|
uint256 nonFeeCashOutCount = context.cashOutCount - feeCashOutCount;
|
|
179
200
|
|
|
180
201
|
// Calculate how much surplus the non-fee tokens can reclaim via the bonding curve.
|
|
202
|
+
// Use effective (cross-chain) surplus; cap at local surplus.
|
|
181
203
|
uint256 postFeeReclaimedAmount = JBCashOuts.cashOutFrom({
|
|
182
|
-
surplus:
|
|
204
|
+
surplus: effectiveSurplusValue,
|
|
183
205
|
cashOutCount: nonFeeCashOutCount,
|
|
184
|
-
totalSupply:
|
|
206
|
+
totalSupply: totalSupply,
|
|
185
207
|
cashOutTaxRate: context.cashOutTaxRate
|
|
186
208
|
});
|
|
209
|
+
// Cap at local surplus — the bonding curve uses cross-chain effective surplus which can exceed what this
|
|
210
|
+
// chain's terminal actually holds.
|
|
211
|
+
if (postFeeReclaimedAmount > context.surplus.value) postFeeReclaimedAmount = context.surplus.value;
|
|
187
212
|
|
|
188
213
|
// Calculate how much the fee tokens reclaim from the remaining surplus after the non-fee reclaim.
|
|
214
|
+
// Use remaining effective surplus; cap at remaining local surplus.
|
|
189
215
|
uint256 feeAmount = JBCashOuts.cashOutFrom({
|
|
190
|
-
surplus:
|
|
216
|
+
surplus: effectiveSurplusValue > postFeeReclaimedAmount
|
|
217
|
+
? effectiveSurplusValue - postFeeReclaimedAmount
|
|
218
|
+
: 0,
|
|
191
219
|
cashOutCount: feeCashOutCount,
|
|
192
|
-
totalSupply:
|
|
220
|
+
totalSupply: totalSupply - nonFeeCashOutCount,
|
|
193
221
|
cashOutTaxRate: context.cashOutTaxRate
|
|
194
222
|
});
|
|
223
|
+
// Cap the fee reclaim at remaining local surplus. The bonding curve uses the cross-chain effective surplus,
|
|
224
|
+
// which can exceed what's actually held locally. Without this cap, the terminal would try to send more than
|
|
225
|
+
// it has.
|
|
226
|
+
if (feeAmount > context.surplus.value - postFeeReclaimedAmount) {
|
|
227
|
+
feeAmount = context.surplus.value - postFeeReclaimedAmount;
|
|
228
|
+
}
|
|
195
229
|
|
|
196
230
|
// Build a context for the buyback hook using only the non-fee token count.
|
|
197
231
|
JBBeforeCashOutRecordedContext memory buybackHookContext = context;
|
|
@@ -199,11 +233,13 @@ contract REVOwner is IJBRulesetDataHook, IJBCashOutHook {
|
|
|
199
233
|
|
|
200
234
|
// Let the buyback hook adjust the cash out parameters and optionally return a hook specification.
|
|
201
235
|
JBCashOutHookSpecification[] memory buybackHookSpecifications;
|
|
202
|
-
(cashOutTaxRate, cashOutCount
|
|
236
|
+
(cashOutTaxRate, cashOutCount,,, buybackHookSpecifications) =
|
|
203
237
|
BUYBACK_HOOK.beforeCashOutRecordedWith(buybackHookContext);
|
|
204
238
|
|
|
205
239
|
// If the fee rounds down to zero, return the buyback hook's response directly — no fee to process.
|
|
206
|
-
if (feeAmount == 0)
|
|
240
|
+
if (feeAmount == 0) {
|
|
241
|
+
return (cashOutTaxRate, cashOutCount, totalSupply, effectiveSurplusValue, buybackHookSpecifications);
|
|
242
|
+
}
|
|
207
243
|
|
|
208
244
|
// Build a hook spec that routes the fee amount to this contract's `afterCashOutRecordedWith` for processing.
|
|
209
245
|
JBCashOutHookSpecification memory feeSpec = JBCashOutHookSpecification({
|
|
@@ -225,7 +261,7 @@ contract REVOwner is IJBRulesetDataHook, IJBCashOutHook {
|
|
|
225
261
|
hookSpecifications[0] = feeSpec;
|
|
226
262
|
}
|
|
227
263
|
|
|
228
|
-
return (cashOutTaxRate, cashOutCount, totalSupply, hookSpecifications);
|
|
264
|
+
return (cashOutTaxRate, cashOutCount, totalSupply, effectiveSurplusValue, hookSpecifications);
|
|
229
265
|
}
|
|
230
266
|
|
|
231
267
|
/// @notice Before a revnet processes an incoming payment, determine the weight and pay hooks to use.
|
|
@@ -302,8 +338,9 @@ contract REVOwner is IJBRulesetDataHook, IJBCashOutHook {
|
|
|
302
338
|
override
|
|
303
339
|
returns (bool)
|
|
304
340
|
{
|
|
305
|
-
// The loans contract, buyback hook (and its delegates), and suckers are allowed to mint
|
|
306
|
-
|
|
341
|
+
// The loans contract, hidden tokens contract, buyback hook (and its delegates), and suckers are allowed to mint
|
|
342
|
+
// the revnet's tokens.
|
|
343
|
+
return addr == LOANS || addr == HIDDEN_TOKENS || addr == address(BUYBACK_HOOK)
|
|
307
344
|
|| BUYBACK_HOOK.hasMintPermissionFor({projectId: revnetId, ruleset: ruleset, addr: addr})
|
|
308
345
|
|| _isSuckerOf({revnetId: revnetId, addr: addr});
|
|
309
346
|
}
|
|
@@ -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,9 +5,9 @@ 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";
|
|
10
|
+
import {IJBSuckerRegistry} from "@bananapus/suckers-v6/src/interfaces/IJBSuckerRegistry.sol";
|
|
11
11
|
import {IPermit2} from "@uniswap/permit2/src/interfaces/IPermit2.sol";
|
|
12
12
|
import {REVLoan} from "../structs/REVLoan.sol";
|
|
13
13
|
import {REVLoanSource} from "../structs/REVLoanSource.sol";
|
|
@@ -164,14 +164,14 @@ interface IREVLoans {
|
|
|
164
164
|
/// @return The prices contract.
|
|
165
165
|
function PRICES() external view returns (IJBPrices);
|
|
166
166
|
|
|
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
167
|
/// @notice The ID of the REV revnet that receives protocol fees from loans.
|
|
172
168
|
/// @return The REV revnet ID.
|
|
173
169
|
function REV_ID() external view returns (uint256);
|
|
174
170
|
|
|
171
|
+
/// @notice The sucker registry used to discover peer chain suckers for cross-chain supply/surplus awareness.
|
|
172
|
+
/// @return The sucker registry.
|
|
173
|
+
function SUCKER_REGISTRY() external view returns (IJBSuckerRegistry);
|
|
174
|
+
|
|
175
175
|
/// @notice The fee percent charged by the REV revnet on each loan, in terms of `JBConstants.MAX_FEE`.
|
|
176
176
|
/// @return The REV prepaid fee percent.
|
|
177
177
|
function REV_PREPAID_FEE_PERCENT() external view returns (uint256);
|
|
@@ -219,6 +219,7 @@ interface IREVLoans {
|
|
|
219
219
|
/// @param collateralCount The amount of tokens to use as collateral for the loan.
|
|
220
220
|
/// @param beneficiary The address that will receive the borrowed funds and fee payment tokens.
|
|
221
221
|
/// @param prepaidFeePercent The fee percent to charge upfront, in terms of `JBConstants.MAX_FEE`.
|
|
222
|
+
/// @param holder The address whose tokens are used as collateral and who receives the loan NFT.
|
|
222
223
|
/// @return loanId The ID of the loan created from borrowing.
|
|
223
224
|
/// @return The loan created from borrowing.
|
|
224
225
|
function borrowFrom(
|
|
@@ -227,7 +228,8 @@ interface IREVLoans {
|
|
|
227
228
|
uint256 minBorrowAmount,
|
|
228
229
|
uint256 collateralCount,
|
|
229
230
|
address payable beneficiary,
|
|
230
|
-
uint256 prepaidFeePercent
|
|
231
|
+
uint256 prepaidFeePercent,
|
|
232
|
+
address holder
|
|
231
233
|
)
|
|
232
234
|
external
|
|
233
235
|
returns (uint256 loanId, REVLoan memory);
|
|
@@ -40,6 +40,8 @@ import {JBArbitrumSucker, JBLayer, IArbGatewayRouter, IInbox} from "@bananapus/s
|
|
|
40
40
|
|
|
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
|
|
|
@@ -211,7 +213,14 @@ contract REVnet_Integrations is TestBaseWorkflow {
|
|
|
211
213
|
HOOK_STORE = new JB721TiersHookStore();
|
|
212
214
|
|
|
213
215
|
EXAMPLE_HOOK = new JB721TiersHook(
|
|
214
|
-
jbDirectory(),
|
|
216
|
+
jbDirectory(),
|
|
217
|
+
jbPermissions(),
|
|
218
|
+
jbPrices(),
|
|
219
|
+
jbRulesets(),
|
|
220
|
+
HOOK_STORE,
|
|
221
|
+
jbSplits(),
|
|
222
|
+
IJB721CheckpointsDeployer(address(new JB721CheckpointsDeployer())),
|
|
223
|
+
multisig()
|
|
215
224
|
);
|
|
216
225
|
|
|
217
226
|
ADDRESS_REGISTRY = new JBAddressRegistry();
|
|
@@ -226,7 +235,8 @@ contract REVnet_Integrations is TestBaseWorkflow {
|
|
|
226
235
|
jbDirectory(),
|
|
227
236
|
FEE_PROJECT_ID,
|
|
228
237
|
SUCKER_REGISTRY,
|
|
229
|
-
makeAddr("loans")
|
|
238
|
+
makeAddr("loans"),
|
|
239
|
+
address(0)
|
|
230
240
|
);
|
|
231
241
|
|
|
232
242
|
REV_DEPLOYER = new REVDeployer{salt: REV_DEPLOYER_SALT}(
|
|
@@ -32,6 +32,8 @@ import {JBSuckerRegistry} from "@bananapus/suckers-v6/src/JBSuckerRegistry.sol";
|
|
|
32
32
|
import {JB721TiersHookDeployer} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
|
|
33
33
|
import {JB721TiersHook} from "@bananapus/721-hook-v6/src/JB721TiersHook.sol";
|
|
34
34
|
import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
|
|
35
|
+
import {JB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/JB721CheckpointsDeployer.sol";
|
|
36
|
+
import {IJB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/interfaces/IJB721CheckpointsDeployer.sol";
|
|
35
37
|
import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
|
|
36
38
|
import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
|
|
37
39
|
import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
|
|
@@ -77,7 +79,14 @@ contract REVAutoIssuanceFuzz_Local is TestBaseWorkflow {
|
|
|
77
79
|
SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
|
|
78
80
|
HOOK_STORE = new JB721TiersHookStore();
|
|
79
81
|
EXAMPLE_HOOK = new JB721TiersHook(
|
|
80
|
-
jbDirectory(),
|
|
82
|
+
jbDirectory(),
|
|
83
|
+
jbPermissions(),
|
|
84
|
+
jbPrices(),
|
|
85
|
+
jbRulesets(),
|
|
86
|
+
HOOK_STORE,
|
|
87
|
+
jbSplits(),
|
|
88
|
+
IJB721CheckpointsDeployer(address(new JB721CheckpointsDeployer())),
|
|
89
|
+
multisig()
|
|
81
90
|
);
|
|
82
91
|
ADDRESS_REGISTRY = new JBAddressRegistry();
|
|
83
92
|
HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
|
|
@@ -89,7 +98,8 @@ contract REVAutoIssuanceFuzz_Local is TestBaseWorkflow {
|
|
|
89
98
|
jbDirectory(),
|
|
90
99
|
FEE_PROJECT_ID,
|
|
91
100
|
SUCKER_REGISTRY,
|
|
92
|
-
makeAddr("loans")
|
|
101
|
+
makeAddr("loans"),
|
|
102
|
+
address(0)
|
|
93
103
|
);
|
|
94
104
|
|
|
95
105
|
REV_DEPLOYER = new REVDeployer{salt: REV_DEPLOYER_SALT}(
|
|
@@ -35,10 +35,13 @@ 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 {REVOwner} from "../src/REVOwner.sol";
|
|
41
43
|
import {IREVDeployer} from "../src/interfaces/IREVDeployer.sol";
|
|
44
|
+
import {MockSuckerRegistry} from "./mock/MockSuckerRegistry.sol";
|
|
42
45
|
|
|
43
46
|
/// @notice Regression tests for REVDeployer.
|
|
44
47
|
contract REVDeployerRegressions is TestBaseWorkflow {
|
|
@@ -83,7 +86,14 @@ contract REVDeployerRegressions is TestBaseWorkflow {
|
|
|
83
86
|
SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
|
|
84
87
|
HOOK_STORE = new JB721TiersHookStore();
|
|
85
88
|
EXAMPLE_HOOK = new JB721TiersHook(
|
|
86
|
-
jbDirectory(),
|
|
89
|
+
jbDirectory(),
|
|
90
|
+
jbPermissions(),
|
|
91
|
+
jbPrices(),
|
|
92
|
+
jbRulesets(),
|
|
93
|
+
HOOK_STORE,
|
|
94
|
+
jbSplits(),
|
|
95
|
+
IJB721CheckpointsDeployer(address(new JB721CheckpointsDeployer())),
|
|
96
|
+
multisig()
|
|
87
97
|
);
|
|
88
98
|
ADDRESS_REGISTRY = new JBAddressRegistry();
|
|
89
99
|
HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
|
|
@@ -92,7 +102,7 @@ contract REVDeployerRegressions is TestBaseWorkflow {
|
|
|
92
102
|
|
|
93
103
|
LOANS_CONTRACT = new REVLoans({
|
|
94
104
|
controller: jbController(),
|
|
95
|
-
|
|
105
|
+
suckerRegistry: IJBSuckerRegistry(address(new MockSuckerRegistry())),
|
|
96
106
|
revId: FEE_PROJECT_ID,
|
|
97
107
|
owner: address(this),
|
|
98
108
|
permit2: permit2(),
|
|
@@ -104,7 +114,8 @@ contract REVDeployerRegressions is TestBaseWorkflow {
|
|
|
104
114
|
jbDirectory(),
|
|
105
115
|
FEE_PROJECT_ID,
|
|
106
116
|
SUCKER_REGISTRY,
|
|
107
|
-
address(LOANS_CONTRACT)
|
|
117
|
+
address(LOANS_CONTRACT),
|
|
118
|
+
address(0)
|
|
108
119
|
);
|
|
109
120
|
|
|
110
121
|
REV_DEPLOYER = new REVDeployer{salt: REV_DEPLOYER_SALT}(
|
|
@@ -41,6 +41,8 @@ import {JBSuckerRegistry} from "@bananapus/suckers-v6/src/JBSuckerRegistry.sol";
|
|
|
41
41
|
import {JB721TiersHookDeployer} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
|
|
42
42
|
import {JB721TiersHook} from "@bananapus/721-hook-v6/src/JB721TiersHook.sol";
|
|
43
43
|
import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
|
|
44
|
+
import {JB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/JB721CheckpointsDeployer.sol";
|
|
45
|
+
import {IJB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/interfaces/IJB721CheckpointsDeployer.sol";
|
|
44
46
|
import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
|
|
45
47
|
import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
|
|
46
48
|
import {mulDiv} from "@prb/math/src/Common.sol";
|
|
@@ -50,6 +52,7 @@ import {BrokenFeeTerminal} from "./helpers/MaliciousContracts.sol";
|
|
|
50
52
|
import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
|
|
51
53
|
import {REVOwner} from "../src/REVOwner.sol";
|
|
52
54
|
import {IREVDeployer} from "../src/interfaces/IREVDeployer.sol";
|
|
55
|
+
import {MockSuckerRegistry} from "./mock/MockSuckerRegistry.sol";
|
|
53
56
|
|
|
54
57
|
// =========================================================================
|
|
55
58
|
// Shared config struct
|
|
@@ -234,7 +237,14 @@ contract REVInvincibility_PropertyTests is TestBaseWorkflow {
|
|
|
234
237
|
SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
|
|
235
238
|
HOOK_STORE = new JB721TiersHookStore();
|
|
236
239
|
EXAMPLE_HOOK = new JB721TiersHook(
|
|
237
|
-
jbDirectory(),
|
|
240
|
+
jbDirectory(),
|
|
241
|
+
jbPermissions(),
|
|
242
|
+
jbPrices(),
|
|
243
|
+
jbRulesets(),
|
|
244
|
+
HOOK_STORE,
|
|
245
|
+
jbSplits(),
|
|
246
|
+
IJB721CheckpointsDeployer(address(new JB721CheckpointsDeployer())),
|
|
247
|
+
multisig()
|
|
238
248
|
);
|
|
239
249
|
ADDRESS_REGISTRY = new JBAddressRegistry();
|
|
240
250
|
HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
|
|
@@ -244,7 +254,7 @@ contract REVInvincibility_PropertyTests is TestBaseWorkflow {
|
|
|
244
254
|
|
|
245
255
|
LOANS_CONTRACT = new REVLoans({
|
|
246
256
|
controller: jbController(),
|
|
247
|
-
|
|
257
|
+
suckerRegistry: IJBSuckerRegistry(address(new MockSuckerRegistry())),
|
|
248
258
|
revId: FEE_PROJECT_ID,
|
|
249
259
|
owner: address(this),
|
|
250
260
|
permit2: permit2(),
|
|
@@ -256,7 +266,8 @@ contract REVInvincibility_PropertyTests is TestBaseWorkflow {
|
|
|
256
266
|
jbDirectory(),
|
|
257
267
|
FEE_PROJECT_ID,
|
|
258
268
|
SUCKER_REGISTRY,
|
|
259
|
-
address(LOANS_CONTRACT)
|
|
269
|
+
address(LOANS_CONTRACT),
|
|
270
|
+
address(0)
|
|
260
271
|
);
|
|
261
272
|
|
|
262
273
|
REV_DEPLOYER = new REVDeployer{salt: REV_DEPLOYER_SALT}(
|
|
@@ -329,7 +340,7 @@ contract REVInvincibility_PropertyTests is TestBaseWorkflow {
|
|
|
329
340
|
REVLoanSource memory source = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: jbMultiTerminal()});
|
|
330
341
|
|
|
331
342
|
vm.prank(user);
|
|
332
|
-
(loanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(user), prepaidFee);
|
|
343
|
+
(loanId,) = LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokenCount, payable(user), prepaidFee, user);
|
|
333
344
|
}
|
|
334
345
|
|
|
335
346
|
// =====================================================================
|
|
@@ -788,7 +799,7 @@ contract REVInvincibility_PropertyTests is TestBaseWorkflow {
|
|
|
788
799
|
|
|
789
800
|
if (borrowableA > 0) {
|
|
790
801
|
vm.prank(userA);
|
|
791
|
-
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokensA, payable(userA), 25);
|
|
802
|
+
LOANS_CONTRACT.borrowFrom(REVNET_ID, source, 0, tokensA, payable(userA), 25, userA);
|
|
792
803
|
}
|
|
793
804
|
|
|
794
805
|
// UserB's tokens should still have proportional cash-out value
|
|
@@ -1019,7 +1030,14 @@ contract REVInvincibility_Invariants is StdInvariant, TestBaseWorkflow {
|
|
|
1019
1030
|
SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
|
|
1020
1031
|
HOOK_STORE = new JB721TiersHookStore();
|
|
1021
1032
|
EXAMPLE_HOOK = new JB721TiersHook(
|
|
1022
|
-
jbDirectory(),
|
|
1033
|
+
jbDirectory(),
|
|
1034
|
+
jbPermissions(),
|
|
1035
|
+
jbPrices(),
|
|
1036
|
+
jbRulesets(),
|
|
1037
|
+
HOOK_STORE,
|
|
1038
|
+
jbSplits(),
|
|
1039
|
+
IJB721CheckpointsDeployer(address(new JB721CheckpointsDeployer())),
|
|
1040
|
+
multisig()
|
|
1023
1041
|
);
|
|
1024
1042
|
ADDRESS_REGISTRY = new JBAddressRegistry();
|
|
1025
1043
|
HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
|
|
@@ -1028,7 +1046,7 @@ contract REVInvincibility_Invariants is StdInvariant, TestBaseWorkflow {
|
|
|
1028
1046
|
|
|
1029
1047
|
LOANS_CONTRACT = new REVLoans({
|
|
1030
1048
|
controller: jbController(),
|
|
1031
|
-
|
|
1049
|
+
suckerRegistry: IJBSuckerRegistry(address(new MockSuckerRegistry())),
|
|
1032
1050
|
revId: FEE_PROJECT_ID,
|
|
1033
1051
|
owner: address(this),
|
|
1034
1052
|
permit2: permit2(),
|
|
@@ -1040,7 +1058,8 @@ contract REVInvincibility_Invariants is StdInvariant, TestBaseWorkflow {
|
|
|
1040
1058
|
jbDirectory(),
|
|
1041
1059
|
FEE_PROJECT_ID,
|
|
1042
1060
|
SUCKER_REGISTRY,
|
|
1043
|
-
address(LOANS_CONTRACT)
|
|
1061
|
+
address(LOANS_CONTRACT),
|
|
1062
|
+
address(0)
|
|
1044
1063
|
);
|
|
1045
1064
|
|
|
1046
1065
|
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
|
@@ -34,11 +34,14 @@ import {JBSuckerRegistry} from "@bananapus/suckers-v6/src/JBSuckerRegistry.sol";
|
|
|
34
34
|
import {JB721TiersHookDeployer} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
|
|
35
35
|
import {JB721TiersHook} from "@bananapus/721-hook-v6/src/JB721TiersHook.sol";
|
|
36
36
|
import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
|
|
37
|
+
import {JB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/JB721CheckpointsDeployer.sol";
|
|
38
|
+
import {IJB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/interfaces/IJB721CheckpointsDeployer.sol";
|
|
37
39
|
import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
|
|
38
40
|
import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
|
|
39
41
|
import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
|
|
40
42
|
import {REVOwner} from "../src/REVOwner.sol";
|
|
41
43
|
import {IREVDeployer} from "../src/interfaces/IREVDeployer.sol";
|
|
44
|
+
import {MockSuckerRegistry} from "./mock/MockSuckerRegistry.sol";
|
|
42
45
|
|
|
43
46
|
/// @notice Full revnet lifecycle E2E: deploy 3-stage -> pay -> advance stages -> cash out.
|
|
44
47
|
contract REVLifecycle_Local is TestBaseWorkflow {
|
|
@@ -91,7 +94,14 @@ contract REVLifecycle_Local is TestBaseWorkflow {
|
|
|
91
94
|
SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
|
|
92
95
|
HOOK_STORE = new JB721TiersHookStore();
|
|
93
96
|
EXAMPLE_HOOK = new JB721TiersHook(
|
|
94
|
-
jbDirectory(),
|
|
97
|
+
jbDirectory(),
|
|
98
|
+
jbPermissions(),
|
|
99
|
+
jbPrices(),
|
|
100
|
+
jbRulesets(),
|
|
101
|
+
HOOK_STORE,
|
|
102
|
+
jbSplits(),
|
|
103
|
+
IJB721CheckpointsDeployer(address(new JB721CheckpointsDeployer())),
|
|
104
|
+
multisig()
|
|
95
105
|
);
|
|
96
106
|
ADDRESS_REGISTRY = new JBAddressRegistry();
|
|
97
107
|
HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
|
|
@@ -100,7 +110,7 @@ contract REVLifecycle_Local is TestBaseWorkflow {
|
|
|
100
110
|
|
|
101
111
|
LOANS_CONTRACT = new REVLoans({
|
|
102
112
|
controller: jbController(),
|
|
103
|
-
|
|
113
|
+
suckerRegistry: IJBSuckerRegistry(address(new MockSuckerRegistry())),
|
|
104
114
|
revId: FEE_PROJECT_ID,
|
|
105
115
|
owner: address(this),
|
|
106
116
|
permit2: permit2(),
|
|
@@ -112,7 +122,8 @@ contract REVLifecycle_Local is TestBaseWorkflow {
|
|
|
112
122
|
jbDirectory(),
|
|
113
123
|
FEE_PROJECT_ID,
|
|
114
124
|
SUCKER_REGISTRY,
|
|
115
|
-
address(LOANS_CONTRACT)
|
|
125
|
+
address(LOANS_CONTRACT),
|
|
126
|
+
address(0)
|
|
116
127
|
);
|
|
117
128
|
|
|
118
129
|
REV_DEPLOYER = new REVDeployer{salt: REV_DEPLOYER_SALT}(
|
|
@@ -39,11 +39,14 @@ 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 {JBTest} from "@bananapus/core-v6/test/helpers/JBTest.sol";
|
|
45
47
|
import {REVOwner} from "../src/REVOwner.sol";
|
|
46
48
|
import {IREVDeployer} from "../src/interfaces/IREVDeployer.sol";
|
|
49
|
+
import {MockSuckerRegistry} from "./mock/MockSuckerRegistry.sol";
|
|
47
50
|
|
|
48
51
|
struct FeeProjectConfig {
|
|
49
52
|
REVConfig configuration;
|
|
@@ -117,7 +120,7 @@ contract REVLoansCallHandler is JBTest {
|
|
|
117
120
|
|
|
118
121
|
REVLoanSource memory sauce = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: TERMINAL});
|
|
119
122
|
(, REVLoan memory lastLoan) =
|
|
120
|
-
LOANS.borrowFrom(REVNET_ID, sauce, borrowable, receivedTokens, payable(USER), prepaidFee);
|
|
123
|
+
LOANS.borrowFrom(REVNET_ID, sauce, borrowable, receivedTokens, payable(USER), prepaidFee, USER);
|
|
121
124
|
|
|
122
125
|
COLLATERAL_SUM += receivedTokens;
|
|
123
126
|
BORROWED_SUM += lastLoan.amount;
|
|
@@ -530,7 +533,14 @@ contract InvariantREVLoansTests is StdInvariant, TestBaseWorkflow {
|
|
|
530
533
|
HOOK_STORE = new JB721TiersHookStore();
|
|
531
534
|
|
|
532
535
|
EXAMPLE_HOOK = new JB721TiersHook(
|
|
533
|
-
jbDirectory(),
|
|
536
|
+
jbDirectory(),
|
|
537
|
+
jbPermissions(),
|
|
538
|
+
jbPrices(),
|
|
539
|
+
jbRulesets(),
|
|
540
|
+
HOOK_STORE,
|
|
541
|
+
jbSplits(),
|
|
542
|
+
IJB721CheckpointsDeployer(address(new JB721CheckpointsDeployer())),
|
|
543
|
+
multisig()
|
|
534
544
|
);
|
|
535
545
|
|
|
536
546
|
ADDRESS_REGISTRY = new JBAddressRegistry();
|
|
@@ -542,7 +552,7 @@ contract InvariantREVLoansTests is StdInvariant, TestBaseWorkflow {
|
|
|
542
552
|
|
|
543
553
|
LOANS_CONTRACT = new REVLoans({
|
|
544
554
|
controller: jbController(),
|
|
545
|
-
|
|
555
|
+
suckerRegistry: IJBSuckerRegistry(address(new MockSuckerRegistry())),
|
|
546
556
|
revId: FEE_PROJECT_ID,
|
|
547
557
|
owner: address(this),
|
|
548
558
|
permit2: permit2(),
|
|
@@ -554,7 +564,8 @@ contract InvariantREVLoansTests is StdInvariant, TestBaseWorkflow {
|
|
|
554
564
|
jbDirectory(),
|
|
555
565
|
FEE_PROJECT_ID,
|
|
556
566
|
SUCKER_REGISTRY,
|
|
557
|
-
address(LOANS_CONTRACT)
|
|
567
|
+
address(LOANS_CONTRACT),
|
|
568
|
+
address(0)
|
|
558
569
|
);
|
|
559
570
|
|
|
560
571
|
REV_DEPLOYER = new REVDeployer{salt: REV_DEPLOYER_SALT}(
|