@rev-net/core-v6 0.0.24 → 0.0.25
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 +27 -0
- package/ARCHITECTURE.md +53 -129
- package/AUDIT_INSTRUCTIONS.md +108 -375
- package/CHANGELOG.md +65 -0
- package/README.md +76 -175
- package/RISKS.md +16 -4
- package/SKILLS.md +30 -391
- package/STYLE_GUIDE.md +59 -20
- package/USER_JOURNEYS.md +55 -478
- package/package.json +3 -3
- package/references/operations.md +311 -0
- package/references/runtime.md +98 -0
- package/script/Deploy.s.sol +12 -12
- package/src/REVLoans.sol +10 -10
- package/src/interfaces/IREVDeployer.sol +1 -1
- package/test/TestSplitWeightE2E.t.sol +10 -7
- package/test/TestSplitWeightFork.t.sol +10 -7
- package/test/fork/ForkTestBase.sol +10 -7
- package/CHANGE_LOG.md +0 -420
package/CHANGE_LOG.md
DELETED
|
@@ -1,420 +0,0 @@
|
|
|
1
|
-
# revnet-core-v6 Changelog (v5 -> v6)
|
|
2
|
-
|
|
3
|
-
This document describes all changes between `revnet-core` (v5, Solidity 0.8.23) and `revnet-core-v6` (v6, Solidity 0.8.28).
|
|
4
|
-
|
|
5
|
-
## 0. REVDeployer/REVOwner Split (post-v6 refactor)
|
|
6
|
-
|
|
7
|
-
### Motivation
|
|
8
|
-
|
|
9
|
-
REVDeployer exceeded the EIP-170 contract size limit (24,576 bytes) at 26,397 bytes. The contract was split into two:
|
|
10
|
-
|
|
11
|
-
| Contract | Size | Role |
|
|
12
|
-
|----------|------|------|
|
|
13
|
-
| `REVDeployer` | 19,746 bytes | Deployment, configuration, state storage, split operator management |
|
|
14
|
-
| `REVOwner` | 8,434 bytes (~310 lines) | Runtime hook behavior: `IJBRulesetDataHook` + `IJBCashOutHook` |
|
|
15
|
-
|
|
16
|
-
### What moved to REVOwner
|
|
17
|
-
|
|
18
|
-
| Function | Description |
|
|
19
|
-
|----------|-------------|
|
|
20
|
-
| `beforePayRecordedWith()` | Pay data hook -- 721 hook delegation, buyback hook delegation, weight scaling |
|
|
21
|
-
| `beforeCashOutRecordedWith()` | Cash-out data hook -- sucker bypass, fee splitting, cash-out delay enforcement |
|
|
22
|
-
| `afterCashOutRecordedWith()` | Cash-out hook callback -- fee payment to fee revnet |
|
|
23
|
-
| `hasMintPermissionFor()` | Mint permission check for loans, buyback hook, suckers |
|
|
24
|
-
| `_isSuckerOf()` | Internal sucker verification helper |
|
|
25
|
-
| `_beforeTransferTo()` | Internal pre-transfer fee handling |
|
|
26
|
-
| `cashOutDelayOf(revnetId)` | View that returns the cash-out delay from REVOwner storage. Exposed via IREVOwner for REVLoans compatibility. |
|
|
27
|
-
|
|
28
|
-
### What REVDeployer retains
|
|
29
|
-
|
|
30
|
-
- `deployFor()` -- revnet deployment (both overloads)
|
|
31
|
-
- `queueStagesToRevnetOf()` -- stage configuration
|
|
32
|
-
- `autoIssueFor()` -- auto-issuance claiming
|
|
33
|
-
- `setSplitOperatorOf()` -- operator management
|
|
34
|
-
- `replaceSplitsOf()` -- split management
|
|
35
|
-
- `deploySuckersFor()` -- sucker deployment
|
|
36
|
-
- Configuration state mappings: `amountToAutoIssue`, `hashedEncodedConfigurationOf`, etc.
|
|
37
|
-
- `OWNER()` -- new view returning the REVOwner address
|
|
38
|
-
- `supportsInterface()` -- no longer includes `IJBRulesetDataHook` or `IJBCashOutHook`
|
|
39
|
-
|
|
40
|
-
### Storage migration: `cashOutDelayOf` and `tiered721HookOf` moved to REVOwner
|
|
41
|
-
|
|
42
|
-
The `cashOutDelayOf` and `tiered721HookOf` storage mappings were moved from REVDeployer to REVOwner. REVOwner now has DEPLOYER-restricted setter functions (`setCashOutDelayOf()` and `setTiered721HookOf()`) that only REVDeployer can call. REVDeployer calls these setters during deployment instead of writing to its own storage.
|
|
43
|
-
|
|
44
|
-
- `cashOutDelayOf` and `tiered721HookOf` removed from `IREVDeployer` interface
|
|
45
|
-
- `IREVOwner.sol` created at `src/interfaces/IREVOwner.sol` (exposes `cashOutDelayOf`)
|
|
46
|
-
- REVLoans now imports `IREVOwner` (not `IREVDeployer`) for `cashOutDelayOf` calls
|
|
47
|
-
- REVOwner reads `cashOutDelayOf` and `tiered721HookOf` directly from its own storage instead of delegating to `DEPLOYER`
|
|
48
|
-
|
|
49
|
-
### Circular dependency pattern
|
|
50
|
-
|
|
51
|
-
REVDeployer needs REVOwner (as the `dataHook` address and to set `cashOutDelayOf`/`tiered721HookOf` via restricted setters), and REVOwner references REVDeployer (to restrict setter access). This circular dependency is broken by:
|
|
52
|
-
|
|
53
|
-
1. Deploy REVOwner first
|
|
54
|
-
2. Deploy REVDeployer with `owner=REVOwner` -- the constructor calls `REVOwner.setDeployer()` atomically
|
|
55
|
-
|
|
56
|
-
`REVOwner.DEPLOYER` is a **storage variable** (not immutable) because the deployer address is not known at REVOwner construction time. `setDeployer()` sets `msg.sender` as `DEPLOYER` and reverts if already set (`REVOwner_AlreadyInitialized`). After initialization, `DEPLOYER` is used to restrict access to `setCashOutDelayOf()` and `setTiered721HookOf()`.
|
|
57
|
-
|
|
58
|
-
### Shared immutables
|
|
59
|
-
|
|
60
|
-
Both contracts independently store these as immutables (set at construction): `BUYBACK_HOOK`, `DIRECTORY`, `FEE_REVNET_ID`, `SUCKER_REGISTRY`, `LOANS`. The `FEE` constant (25 = 2.5%) is defined in both contracts.
|
|
61
|
-
|
|
62
|
-
### Interface changes
|
|
63
|
-
|
|
64
|
-
| Change | Description |
|
|
65
|
-
|--------|-------------|
|
|
66
|
-
| `IREVDeployer.OWNER()` | New view function returning the REVOwner address |
|
|
67
|
-
| `IREVDeployer` | `cashOutDelayOf` and `tiered721HookOf` removed (moved to REVOwner) |
|
|
68
|
-
| `IREVOwner.sol` | New interface at `src/interfaces/IREVOwner.sol` — exposes `cashOutDelayOf` |
|
|
69
|
-
| `REVOwner.setCashOutDelayOf()` | New DEPLOYER-restricted setter for `cashOutDelayOf` |
|
|
70
|
-
| `REVOwner.setTiered721HookOf()` | New DEPLOYER-restricted setter for `tiered721HookOf` |
|
|
71
|
-
| `REVDeployer.supportsInterface()` | No longer reports `IJBRulesetDataHook` or `IJBCashOutHook` |
|
|
72
|
-
| Ruleset `metadata.dataHook` | Now set to `address(REVOwner)` instead of `address(REVDeployer)` |
|
|
73
|
-
|
|
74
|
-
### Migration impact
|
|
75
|
-
|
|
76
|
-
- **Indexers/subgraphs**: Data hook events now originate from the REVOwner address, not REVDeployer. `cashOutDelayOf` and `tiered721HookOf` storage reads must target REVOwner, not REVDeployer.
|
|
77
|
-
- **REVLoans**: Now imports `IREVOwner` (not `IREVDeployer`) and calls `REVOwner.cashOutDelayOf(revnetId)` directly from REVOwner storage.
|
|
78
|
-
- **Direct callers**: Any code that read `cashOutDelayOf` or `tiered721HookOf` from REVDeployer must now read from REVOwner. Any code that cast the deployer address to `IJBRulesetDataHook` or `IJBCashOutHook` must now use the REVOwner address instead.
|
|
79
|
-
|
|
80
|
-
---
|
|
81
|
-
|
|
82
|
-
## Summary
|
|
83
|
-
|
|
84
|
-
- **Buyback hook centralized**: Per-revnet `buybackHookOf` mapping replaced by a single immutable `BUYBACK_HOOK` registry — pools auto-initialized with default parameters during deployment.
|
|
85
|
-
- **Loans simplified**: Per-revnet `loansOf` mapping replaced by a single immutable `LOANS` address; fund access limits derived automatically from terminal configurations.
|
|
86
|
-
- **Every revnet gets a 721 hook**: The 4-arg `deployFor` overload auto-deploys an empty-tier 721 hook. `deployWith721sFor` merged into a 6-arg `deployFor` overload.
|
|
87
|
-
- **Permission flags inverted**: `splitOperatorCan*` (opt-in) → `preventSplitOperator*` (opt-out) — permissions granted by default unless explicitly prevented.
|
|
88
|
-
- **Weight scaling for tier splits**: `beforePayRecordedWith` now reduces minting weight proportionally when 721 tier splits consume part of the payment, preventing double-counting.
|
|
89
|
-
|
|
90
|
-
---
|
|
91
|
-
|
|
92
|
-
## 1. Breaking Changes
|
|
93
|
-
|
|
94
|
-
### 1.1 Removed Structs
|
|
95
|
-
|
|
96
|
-
| Struct | Notes |
|
|
97
|
-
|--------|-------|
|
|
98
|
-
| `REVBuybackHookConfig` | Removed entirely. Buyback hook configuration is no longer passed by the caller. The deployer auto-configures buyback pools via an immutable `BUYBACK_HOOK` registry. |
|
|
99
|
-
| `REVBuybackPoolConfig` | Removed entirely. Was used within `REVBuybackHookConfig`. Buyback pools are now auto-initialized with default parameters. |
|
|
100
|
-
|
|
101
|
-
### 1.2 Struct Field Changes
|
|
102
|
-
|
|
103
|
-
#### REVConfig
|
|
104
|
-
|
|
105
|
-
| Change | v5 | v6 |
|
|
106
|
-
|--------|----|----|
|
|
107
|
-
| `loanSources` field | `REVLoanSource[] loanSources` | Removed |
|
|
108
|
-
| `loans` field | `address loans` | Removed |
|
|
109
|
-
|
|
110
|
-
Loan sources and the loans contract address are no longer part of the per-revnet configuration. In v6, loans are managed via a single immutable `LOANS` address on the deployer, and fund access limits for loans are derived from terminal configurations rather than explicit loan sources.
|
|
111
|
-
|
|
112
|
-
#### REVDeploy721TiersHookConfig
|
|
113
|
-
|
|
114
|
-
| Change | v5 | v6 |
|
|
115
|
-
|--------|----|----|
|
|
116
|
-
| `baseline721HookConfiguration` type | `JBDeploy721TiersHookConfig` | `REVBaseline721HookConfig` |
|
|
117
|
-
| `splitOperatorCanAdjustTiers` | `bool splitOperatorCanAdjustTiers` | Renamed to `bool preventSplitOperatorAdjustingTiers` |
|
|
118
|
-
| `splitOperatorCanUpdateMetadata` | `bool splitOperatorCanUpdateMetadata` | Renamed to `bool preventSplitOperatorUpdatingMetadata` |
|
|
119
|
-
| `splitOperatorCanMint` | `bool splitOperatorCanMint` | Renamed to `bool preventSplitOperatorMinting` |
|
|
120
|
-
| `splitOperatorCanIncreaseDiscountPercent` | `bool splitOperatorCanIncreaseDiscountPercent` | Renamed to `bool preventSplitOperatorIncreasingDiscountPercent` |
|
|
121
|
-
|
|
122
|
-
The boolean semantics are **inverted**: v5 used opt-in flags (`splitOperatorCan*`), v6 uses opt-out flags (`preventSplitOperator*`). In v6, the permissions are granted by default unless explicitly prevented.
|
|
123
|
-
|
|
124
|
-
#### REVCroptopAllowedPost
|
|
125
|
-
|
|
126
|
-
| Change | v5 | v6 |
|
|
127
|
-
|--------|----|----|
|
|
128
|
-
| `maximumSplitPercent` field | Not present | Added: `uint32 maximumSplitPercent` |
|
|
129
|
-
|
|
130
|
-
### 1.3 IREVDeployer Interface Changes
|
|
131
|
-
|
|
132
|
-
| Change | v5 | v6 |
|
|
133
|
-
|--------|----|----|
|
|
134
|
-
| `deployFor` (no 721s) return type | `returns (uint256)` | `returns (uint256, IJB721TiersHook)` |
|
|
135
|
-
| `deployFor` (no 721s) parameters | `(uint256, REVConfig, JBTerminalConfig[], REVBuybackHookConfig, REVSuckerDeploymentConfig)` | `(uint256, REVConfig, JBTerminalConfig[], REVSuckerDeploymentConfig)` |
|
|
136
|
-
| `deployWith721sFor` | `deployWith721sFor(uint256, REVConfig, JBTerminalConfig[], REVBuybackHookConfig, REVSuckerDeploymentConfig, REVDeploy721TiersHookConfig, REVCroptopAllowedPost[])` | Removed. Replaced by `deployFor` overload with 6 parameters. |
|
|
137
|
-
| `buybackHookOf` view | `buybackHookOf(uint256) returns (IJBRulesetDataHook)` | Removed. Replaced by immutable `BUYBACK_HOOK()`. |
|
|
138
|
-
| `loansOf` view | `loansOf(uint256) returns (address)` | Removed. Replaced by immutable `LOANS()`. |
|
|
139
|
-
|
|
140
|
-
### 1.4 IREVLoans Interface Changes
|
|
141
|
-
|
|
142
|
-
| Change | v5 | v6 |
|
|
143
|
-
|--------|----|----|
|
|
144
|
-
| `REVNETS` view | `REVNETS() returns (IREVDeployer)` | Removed. The loans contract no longer stores a reference to the deployer. |
|
|
145
|
-
| `numberOfLoansFor` view | `numberOfLoansFor(uint256) returns (uint256)` | Renamed to `totalLoansBorrowedFor(uint256) returns (uint256)` |
|
|
146
|
-
| `reallocateCollateralFromLoan` mutability | `external payable` | `external` (not payable) |
|
|
147
|
-
| Constructor | `constructor(IREVDeployer, uint256, address, IPermit2, address)` | `constructor(IJBController, IJBProjects, uint256, address, IPermit2, address)` |
|
|
148
|
-
|
|
149
|
-
### 1.5 Removed Errors
|
|
150
|
-
|
|
151
|
-
| Contract | v5 Error | v6 Replacement |
|
|
152
|
-
|----------|----------|----------------|
|
|
153
|
-
| `REVDeployer` | `REVDeployer_LoanSourceDoesntMatchTerminalConfigurations(address, address)` | Removed. Loan sources are no longer validated against terminal configurations. |
|
|
154
|
-
| `REVLoans` | `REVLoans_RevnetsMismatch(address, address)` | Replaced by `REVLoans_InvalidTerminal(address, uint256)`. Terminal validation replaces deployer ownership check. |
|
|
155
|
-
|
|
156
|
-
---
|
|
157
|
-
|
|
158
|
-
## 2. New Features
|
|
159
|
-
|
|
160
|
-
### 2.1 New Functions
|
|
161
|
-
|
|
162
|
-
#### IREVDeployer / REVDeployer
|
|
163
|
-
|
|
164
|
-
| Function | Description |
|
|
165
|
-
|----------|-------------|
|
|
166
|
-
| `burnHeldTokensOf(uint256 revnetId)` | Burns any of the revnet's tokens held by the deployer contract. Project tokens can accumulate here from reserved token distribution when splits do not sum to 100%. |
|
|
167
|
-
| `deployFor` (4-arg overload) | Convenience overload that deploys a revnet with a default empty 721 hook. Constructs an empty 721 config internally. Returns `(uint256, IJB721TiersHook)`. |
|
|
168
|
-
| `BUYBACK_HOOK()` | Returns the immutable `IJBBuybackHookRegistry` used as a data hook to route payments through buyback pools. |
|
|
169
|
-
| `LOANS()` | Returns the immutable address of the single loan contract shared by all revnets. |
|
|
170
|
-
| `DEFAULT_BUYBACK_POOL_FEE()` | Returns the default Uniswap pool fee tier (`10_000` = 1%) for auto-configured buyback pools. |
|
|
171
|
-
| `DEFAULT_BUYBACK_TWAP_WINDOW()` | Returns the default TWAP window (`2 days`) for auto-configured buyback pools. |
|
|
172
|
-
|
|
173
|
-
### 2.2 New Events
|
|
174
|
-
|
|
175
|
-
| Contract | Event |
|
|
176
|
-
|----------|-------|
|
|
177
|
-
| `IREVDeployer` | `BurnHeldTokens(uint256 indexed revnetId, uint256 count, address caller)` |
|
|
178
|
-
|
|
179
|
-
### 2.3 New Errors
|
|
180
|
-
|
|
181
|
-
| Contract | Error |
|
|
182
|
-
|----------|-------|
|
|
183
|
-
| `REVDeployer` | `REVDeployer_NothingToBurn()` |
|
|
184
|
-
| `REVLoans` | `REVLoans_InvalidTerminal(address terminal, uint256 revnetId)` |
|
|
185
|
-
| `REVLoans` | `REVLoans_NothingToRepay()` |
|
|
186
|
-
| `REVLoans` | `REVLoans_ZeroBorrowAmount()` |
|
|
187
|
-
| `REVLoans` | `REVLoans_SourceMismatch()` |
|
|
188
|
-
| `REVLoans` | `REVLoans_CashOutDelayNotFinished(uint256 cashOutDelay, uint256 blockTimestamp)` |
|
|
189
|
-
| `REVLoans` | `REVLoans_LoanIdOverflow()` |
|
|
190
|
-
|
|
191
|
-
### 2.4 New Constants
|
|
192
|
-
|
|
193
|
-
| Contract | Constant | Description |
|
|
194
|
-
|----------|----------|-------------|
|
|
195
|
-
| `REVDeployer` | `DEFAULT_BUYBACK_POOL_FEE = 10_000` | Default Uniswap pool fee tier (1%) for auto-configured buyback pools. |
|
|
196
|
-
| `REVDeployer` | `DEFAULT_BUYBACK_TICK_SPACING = 200` | Default tick spacing for buyback pools, aligned with `UniV4DeploymentSplitHook.TICK_SPACING`. |
|
|
197
|
-
| `REVDeployer` | `DEFAULT_BUYBACK_TWAP_WINDOW = 2 days` | Default TWAP window for buyback pools. |
|
|
198
|
-
|
|
199
|
-
### 2.5 New Structs
|
|
200
|
-
|
|
201
|
-
| Struct | Description |
|
|
202
|
-
|--------|-------------|
|
|
203
|
-
| `REVBaseline721HookConfig` | Replaces `JBDeploy721TiersHookConfig` as the type for `REVDeploy721TiersHookConfig.baseline721HookConfiguration`. Contains `name`, `symbol`, `baseUri`, `tokenUriResolver`, `contractUri`, `tiersConfig`, `reserveBeneficiary`, and `flags` (`REV721TiersHookFlags`). |
|
|
204
|
-
| `REV721TiersHookFlags` | A subset of `JB721TiersHookFlags` that omits `issueTokensForSplits` (revnets always force it to `false`). Contains `noNewTiersWithReserves`, `noNewTiersWithVotes`, `noNewTiersWithOwnerMinting`, `preventOverspending`. |
|
|
205
|
-
|
|
206
|
-
---
|
|
207
|
-
|
|
208
|
-
## 3. Event Changes
|
|
209
|
-
|
|
210
|
-
### 3.0 Indexer Notes
|
|
211
|
-
|
|
212
|
-
For revnet-focused subgraphs:
|
|
213
|
-
- both deployment flows now correlate to `deployFor` rather than a split `deployFor`/`deployWith721sFor` model;
|
|
214
|
-
- revnet deployment entities should expect an associated 721 hook by default;
|
|
215
|
-
- any entity that previously depended on caller-supplied buyback-hook config should be updated for the v6 auto-configured buyback path.
|
|
216
|
-
|
|
217
|
-
### 3.1 Added Events
|
|
218
|
-
|
|
219
|
-
See section 2.2 above.
|
|
220
|
-
|
|
221
|
-
### 3.2 Removed Events
|
|
222
|
-
|
|
223
|
-
| Contract | Event | Notes |
|
|
224
|
-
|----------|-------|-------|
|
|
225
|
-
| `IREVDeployer` | `SetAdditionalOperator(uint256 revnetId, address additionalOperator, uint256[] permissionIds, address caller)` | Removed entirely. |
|
|
226
|
-
|
|
227
|
-
### 3.3 Modified Events
|
|
228
|
-
|
|
229
|
-
| Contract | Event | Change |
|
|
230
|
-
|----------|-------|--------|
|
|
231
|
-
| `IREVDeployer` | `DeployRevnet` | Removed `REVBuybackHookConfig buybackHookConfiguration` parameter. |
|
|
232
|
-
| `IREVLoans` | `ReallocateCollateral` | Typo fix: `removedcollateralCount` (lowercase 'c') renamed to `removedCollateralCount` (uppercase 'C'). |
|
|
233
|
-
|
|
234
|
-
### 3.4 NatSpec Documentation
|
|
235
|
-
|
|
236
|
-
All events in v6 interfaces gained comprehensive NatSpec documentation (`@notice`, `@param`). This is a documentation-only change that does not affect the ABI.
|
|
237
|
-
|
|
238
|
-
---
|
|
239
|
-
|
|
240
|
-
## 4. Error Changes
|
|
241
|
-
|
|
242
|
-
### 4.1 Removed Errors
|
|
243
|
-
|
|
244
|
-
| Contract | Error | Notes |
|
|
245
|
-
|----------|-------|-------|
|
|
246
|
-
| `REVDeployer` | `REVDeployer_LoanSourceDoesntMatchTerminalConfigurations(address, address)` | Loan sources removed from `REVConfig`. |
|
|
247
|
-
| `REVLoans` | `REVLoans_RevnetsMismatch(address, address)` | Replaced by terminal validation via `DIRECTORY.isTerminalOf`. |
|
|
248
|
-
|
|
249
|
-
### 4.2 New Errors
|
|
250
|
-
|
|
251
|
-
See section 2.3 above.
|
|
252
|
-
|
|
253
|
-
### 4.3 Unchanged Errors
|
|
254
|
-
|
|
255
|
-
The following errors are identical between v5 and v6:
|
|
256
|
-
|
|
257
|
-
**REVDeployer:**
|
|
258
|
-
- `REVDeployer_AutoIssuanceBeneficiaryZeroAddress()`
|
|
259
|
-
- `REVDeployer_CashOutDelayNotFinished(uint256, uint256)`
|
|
260
|
-
- `REVDeployer_CashOutsCantBeTurnedOffCompletely(uint256, uint256)`
|
|
261
|
-
- `REVDeployer_MustHaveSplits()`
|
|
262
|
-
- `REVDeployer_NothingToAutoIssue()`
|
|
263
|
-
- `REVDeployer_RulesetDoesNotAllowDeployingSuckers()`
|
|
264
|
-
- `REVDeployer_StageNotStarted(uint256)`
|
|
265
|
-
- `REVDeployer_StagesRequired()`
|
|
266
|
-
- `REVDeployer_StageTimesMustIncrease()`
|
|
267
|
-
- `REVDeployer_Unauthorized(uint256, address)`
|
|
268
|
-
|
|
269
|
-
**REVLoans:**
|
|
270
|
-
- `REVLoans_CollateralExceedsLoan(uint256, uint256)`
|
|
271
|
-
- `REVLoans_InvalidPrepaidFeePercent(uint256, uint256, uint256)`
|
|
272
|
-
- `REVLoans_LoanExpired(uint256, uint256)`
|
|
273
|
-
- `REVLoans_NewBorrowAmountGreaterThanLoanAmount(uint256, uint256)`
|
|
274
|
-
- `REVLoans_NoMsgValueAllowed()`
|
|
275
|
-
- `REVLoans_NotEnoughCollateral()`
|
|
276
|
-
- `REVLoans_OverflowAlert(uint256, uint256)`
|
|
277
|
-
- `REVLoans_OverMaxRepayBorrowAmount(uint256, uint256)`
|
|
278
|
-
- `REVLoans_PermitAllowanceNotEnough(uint256, uint256)`
|
|
279
|
-
- `REVLoans_ReallocatingMoreCollateralThanBorrowedAmountAllows(uint256, uint256)`
|
|
280
|
-
- `REVLoans_Unauthorized(address, address)`
|
|
281
|
-
- `REVLoans_UnderMinBorrowAmount(uint256, uint256)`
|
|
282
|
-
- `REVLoans_ZeroCollateralLoanIsInvalid()`
|
|
283
|
-
|
|
284
|
-
---
|
|
285
|
-
|
|
286
|
-
## 5. Struct Changes
|
|
287
|
-
|
|
288
|
-
### 5.1 Removed Structs
|
|
289
|
-
|
|
290
|
-
| Struct | Notes |
|
|
291
|
-
|--------|-------|
|
|
292
|
-
| `REVBuybackHookConfig` | Buyback hook is now an immutable on the deployer; configuration is automatic. |
|
|
293
|
-
| `REVBuybackPoolConfig` | Was used within `REVBuybackHookConfig`. |
|
|
294
|
-
|
|
295
|
-
### 5.2 New Structs
|
|
296
|
-
|
|
297
|
-
| Struct | Notes |
|
|
298
|
-
|--------|-------|
|
|
299
|
-
| `REVBaseline721HookConfig` | Replaces `JBDeploy721TiersHookConfig` in `REVDeploy721TiersHookConfig`. Provides a revnet-specific 721 config that uses `REV721TiersHookFlags` instead of `JB721TiersHookFlags`, omitting `issueTokensForSplits`. |
|
|
300
|
-
| `REV721TiersHookFlags` | A subset of `JB721TiersHookFlags` without `issueTokensForSplits` (always forced to `false` for revnets). |
|
|
301
|
-
|
|
302
|
-
### 5.3 Modified Structs
|
|
303
|
-
|
|
304
|
-
| Struct | Field | v5 | v6 |
|
|
305
|
-
|--------|-------|----|----|
|
|
306
|
-
| `REVConfig` | `loanSources` | `REVLoanSource[] loanSources` | Removed |
|
|
307
|
-
| `REVConfig` | `loans` | `address loans` | Removed |
|
|
308
|
-
| `REVCroptopAllowedPost` | `maximumSplitPercent` | Not present | `uint32 maximumSplitPercent` |
|
|
309
|
-
| `REVDeploy721TiersHookConfig` | `baseline721HookConfiguration` | `JBDeploy721TiersHookConfig` | `REVBaseline721HookConfig` |
|
|
310
|
-
| `REVDeploy721TiersHookConfig` | `splitOperatorCanAdjustTiers` | `bool splitOperatorCanAdjustTiers` | Renamed/inverted: `bool preventSplitOperatorAdjustingTiers` |
|
|
311
|
-
| `REVDeploy721TiersHookConfig` | `splitOperatorCanUpdateMetadata` | `bool splitOperatorCanUpdateMetadata` | Renamed/inverted: `bool preventSplitOperatorUpdatingMetadata` |
|
|
312
|
-
| `REVDeploy721TiersHookConfig` | `splitOperatorCanMint` | `bool splitOperatorCanMint` | Renamed/inverted: `bool preventSplitOperatorMinting` |
|
|
313
|
-
| `REVDeploy721TiersHookConfig` | `splitOperatorCanIncreaseDiscountPercent` | `bool splitOperatorCanIncreaseDiscountPercent` | Renamed/inverted: `bool preventSplitOperatorIncreasingDiscountPercent` |
|
|
314
|
-
|
|
315
|
-
### 5.4 Unchanged Structs
|
|
316
|
-
|
|
317
|
-
The following structs are identical between v5 and v6 (only `forge-lint` comments added):
|
|
318
|
-
- `REVAutoIssuance`
|
|
319
|
-
- `REVDescription`
|
|
320
|
-
- `REVLoan`
|
|
321
|
-
- `REVLoanSource`
|
|
322
|
-
- `REVStageConfig`
|
|
323
|
-
- `REVSuckerDeploymentConfig`
|
|
324
|
-
|
|
325
|
-
---
|
|
326
|
-
|
|
327
|
-
## 6. Implementation Changes
|
|
328
|
-
|
|
329
|
-
### 6.1 REVDeployer
|
|
330
|
-
|
|
331
|
-
| Change | Description |
|
|
332
|
-
|--------|-------------|
|
|
333
|
-
| **Solidity version** | Upgraded from `0.8.23` to `0.8.28`. |
|
|
334
|
-
| **Buyback hook architecture** | Per-revnet `buybackHookOf` mapping replaced with a single immutable `BUYBACK_HOOK` (`IJBBuybackHookRegistry`). Pools are auto-initialized for each terminal token during deployment via `_tryInitializeBuybackPoolFor`. |
|
|
335
|
-
| **Loans architecture** | Per-revnet `loansOf` mapping replaced with a single immutable `LOANS` address. The deployer grants `USE_ALLOWANCE` permission to the loans contract for all revnets in the constructor (wildcard `revnetId=0`). |
|
|
336
|
-
| **Constructor permissions** | v6 constructor grants three wildcard permissions: `MAP_SUCKER_TOKEN` to the sucker registry, `USE_ALLOWANCE` to the loans contract, and `SET_BUYBACK_POOL` to the buyback hook. v5 only granted `MAP_SUCKER_TOKEN`. |
|
|
337
|
-
| **Deploy function consolidation** | `deployFor` and `deployWith721sFor` merged into two `deployFor` overloads: a 6-arg version (with 721 config and allowed posts) and a 4-arg convenience version (auto-creates empty 721 hook). Both return `(uint256, IJB721TiersHook)`. |
|
|
338
|
-
| **Every revnet gets a 721 hook** | The 4-arg `deployFor` overload auto-deploys a default empty 721 hook with all split operator permissions granted. In v5, the simple `deployFor` did not deploy any 721 hook. |
|
|
339
|
-
| **721 permission semantics inverted** | v5 used opt-in flags (`splitOperatorCanAdjustTiers` etc.) that conditionally pushed permissions. v6 uses opt-out flags (`preventSplitOperatorAdjustingTiers` etc.) that grant permissions by default unless prevented. |
|
|
340
|
-
| **`beforePayRecordedWith` rewrite** | v5 fetched the buyback hook from `buybackHookOf[revnetId]` and the 721 hook separately, passing the 721 hook as a zero-amount `JBPayHookSpecification`. v6 queries the 721 hook first as a data hook to determine its tier split amount, reduces the payment context amount for the buyback hook query, and scales the buyback weight proportionally (`weight * projectAmount / totalAmount`) to prevent minting tokens for the split portion of payments. |
|
|
341
|
-
|
|
342
|
-
> **Why weight scaling matters**: Without proportional scaling, a payment of 1 ETH where 0.3 ETH goes to tier splits would still mint tokens as if the full 1 ETH entered the treasury. The `mulDiv(weight, projectAmount, totalAmount)` formula ensures tokens are only minted for the 0.7 ETH that actually enters the project, preventing dilution of existing token holders.
|
|
343
|
-
|
|
344
|
-
| **`hasMintPermissionFor` updated** | v5 checked `loansOf[revnetId]`, `buybackHookOf[revnetId]`, and suckers. v6 checks the immutable `LOANS`, the immutable `BUYBACK_HOOK`, and delegates to `BUYBACK_HOOK.hasMintPermissionFor` for buyback delegates. |
|
|
345
|
-
| **Loan fund access limits simplified** | v5 derived fund access limits from `configuration.loanSources` and validated them against terminal configurations via `_matchingCurrencyOf`. v6 derives them from all terminal configurations directly (one unlimited surplus allowance per terminal+token pair). The `_matchingCurrencyOf` helper is removed. |
|
|
346
|
-
| **`burnHeldTokensOf` added** | New function to burn any project tokens held by the deployer. Reverts with `REVDeployer_NothingToBurn` if the balance is zero. |
|
|
347
|
-
| **Split operator permissions expanded** | Default permissions increased from 6 (v5) to 9 (v6). Added `SET_BUYBACK_HOOK`, `SET_ROUTER_TERMINAL`, and `SET_TOKEN_METADATA`. |
|
|
348
|
-
| **Encoded configuration hash** | v5 included `configuration.loans` in the encoded configuration. v6 does not, since loans are no longer per-revnet. |
|
|
349
|
-
| **Deploy ordering** | v6 `_deploy721RevnetFor` deploys the revnet first via `_deployRevnetFor`, then deploys the 721 hook and sets split operator permissions. v5 deployed the 721 hook then called `_deployRevnetFor`. |
|
|
350
|
-
| **Croptop `maximumSplitPercent`** | v6 passes the new `maximumSplitPercent` field from `REVCroptopAllowedPost` to `CTAllowedPost`. |
|
|
351
|
-
| **Auto-initialized buyback pools** | During deployment, `_tryInitializeBuybackPoolFor` is called for every terminal token to set up Uniswap V4 buyback pools at a generic 1:1 `sqrtPriceX96`. Failures (e.g., pool already initialized) are silently caught via try-catch. |
|
|
352
|
-
| **Feeless beneficiary cashout routing** | `beforeCashOutRecordedWith` now checks `context.beneficiaryIsFeeless` and skips the 2.5% revnet fee when the cashout is routed by a feeless address (e.g., the router terminal routing value between projects). v5 did not have this check. The cash out tax rate still applies -- only the protocol fee is waived. |
|
|
353
|
-
|
|
354
|
-
### 6.2 REVLoans
|
|
355
|
-
|
|
356
|
-
| Change | Description |
|
|
357
|
-
|--------|-------------|
|
|
358
|
-
| **Solidity version** | Upgraded from `0.8.23` to `0.8.28`. |
|
|
359
|
-
| **Deployer dependency removed** | v5 stored `REVNETS` (`IREVDeployer`) and validated that the revnet was owned by the expected deployer via `RevnetsMismatch`. v6 does not reference the deployer at all. Validation now checks the terminal directly via `DIRECTORY.isTerminalOf`. |
|
|
360
|
-
| **Constructor refactored** | v5 accepted `IREVDeployer revnets` and derived `CONTROLLER`, `DIRECTORY`, etc. from it. v6 accepts `IJBController controller` and `IJBProjects projects` directly. |
|
|
361
|
-
| **Terminal validation** | `borrowFrom` now validates that the source terminal is registered in the directory for the revnet, reverting with `REVLoans_InvalidTerminal` if not. v5 validated deployer ownership instead. |
|
|
362
|
-
| **`numberOfLoansFor` renamed** | Renamed to `totalLoansBorrowedFor` to clarify that it is a monotonically increasing counter, not a count of active loans. |
|
|
363
|
-
| **`reallocateCollateralFromLoan` not payable** | v5 marked this function as `external payable`. v6 removes `payable` since the function only moves existing collateral between loans and does not accept new funds. |
|
|
364
|
-
| **Source mismatch check** | `reallocateCollateralFromLoan` now validates that the provided source matches the existing loan's source, reverting with `REVLoans_SourceMismatch()` if they differ. |
|
|
365
|
-
| **Zero borrow amount check** | `borrowFrom` now reverts with `REVLoans_ZeroBorrowAmount()` if the bonding curve returns zero. v5 did not have this check and would create a zero-amount loan. |
|
|
366
|
-
| **Nothing to repay check** | `repayLoan` now reverts with `REVLoans_NothingToRepay()` if both `repayBorrowAmount` and `collateralCountToReturn` are zero, preventing unbounded `totalLoansBorrowedFor` inflation. |
|
|
367
|
-
| **Liquidation loop behavior** | v5 broke out of the loop when encountering a loan with `createdAt == 0` (`break`). v6 continues iterating (`continue`), skipping gaps from repaid or previously liquidated loans. |
|
|
368
|
-
| **Liquidation cleanup** | v6 adds `delete _loanOf[loanId]` after burning a liquidated loan, clearing stale loan data for a gas refund. v5 did not clean up the loan data. |
|
|
369
|
-
| **`_totalBorrowedFrom` decimal normalization** | v6 normalizes token amounts from the source's native decimals to the target decimals before currency conversion. v5 did not perform decimal normalization, which could cause mixed-decimal arithmetic errors for tokens with non-18 decimals (e.g., USDC with 6 decimals). |
|
|
370
|
-
| **`_totalBorrowedFrom` zero-price safety** | v6 skips sources with a zero price to prevent division-by-zero panics that would DoS all loan operations. v5 did not handle this case. |
|
|
371
|
-
| **`_determineSourceFeeAmount` boundary fix** | An intermediate v6 revision used `>=` for the liquidation check, which created a 1-second window where neither repay nor liquidate could execute. This was fixed back to `>` (matching v5) so the exact boundary second is still repayable, while the liquidation path uses `<=`. |
|
|
372
|
-
| **BURN_TOKENS permission prerequisite (NatSpec only)** | `borrowFrom` documents via a `@dev` NatSpec comment that callers must first grant `BURN_TOKENS` permission to the loans contract via `JBPermissions.setPermissionsFor()`. This is required because collateral posting burns the caller's tokens through the controller. However, there is no runtime `hasPermission` check in `borrowFrom` itself -- if the permission is missing, the transaction will revert later inside `JBController.burnTokensOf`. v5 did not document this requirement. |
|
|
373
|
-
| **Cross-revnet liquidation guard** | `liquidateExpiredLoansFrom` now validates that `startingLoanId + count` does not exceed `_ONE_TRILLION`, preventing callers from overflowing into a different revnet's loan ID namespace via `_generateLoanId`. Reverts with `REVLoans_LoanIdOverflow()`. v5 did not have this bounds check. |
|
|
374
|
-
| **Source fee try-catch hardening** | The source fee payment in `_adjust` is now wrapped in a try-catch block. If the source terminal's `pay` call reverts, the ERC-20 allowance is reclaimed and the fee amount is returned to the beneficiary instead of blocking the entire loan operation. v5 called `terminal.pay` directly without error handling. |
|
|
375
|
-
| **Timestamp cast fix** | `borrowFrom` now casts `block.timestamp` to `uint48` when setting `loan.createdAt`, matching the `REVLoan.createdAt` field width. v5 used `uint40`, which would silently truncate timestamps after the year 36812. |
|
|
376
|
-
| **`ReallocateCollateral` event typo fix** | v5 used `removedcollateralCount` (lowercase 'c'). v6 fixes it to `removedCollateralCount` (uppercase 'C'). |
|
|
377
|
-
| **Cash out delay enforced in loans** | `borrowFrom` now resolves REVOwner from the ruleset's `dataHook` and checks `IREVOwner.cashOutDelayOf(revnetId)` (stored on REVOwner). If the 30-day cross-chain deployment delay hasn't passed, `borrowFrom` reverts with `REVLoans_CashOutDelayNotFinished`. `borrowableAmountFrom` returns 0 during the delay so UIs reflect the restriction. v5 did not enforce the cash out delay in the loans contract. |
|
|
378
|
-
| **NatSpec documentation** | Extensive NatSpec added to all functions, views, and internal helpers. Flash loan safety analysis documented in `_borrowableAmountFrom`. |
|
|
379
|
-
|
|
380
|
-
### 6.3 Named Arguments
|
|
381
|
-
|
|
382
|
-
Throughout the codebase, function calls were updated to use named argument syntax (e.g., `foo({bar: 1, baz: 2})`) for improved readability.
|
|
383
|
-
|
|
384
|
-
---
|
|
385
|
-
|
|
386
|
-
## 7. Migration Table
|
|
387
|
-
|
|
388
|
-
### Interfaces
|
|
389
|
-
|
|
390
|
-
| v5 | v6 | Notes |
|
|
391
|
-
|----|----|-------|
|
|
392
|
-
| `IREVDeployer` | `IREVDeployer` | `deployWith721sFor` removed; two `deployFor` overloads (both return `IJB721TiersHook`). `buybackHookOf` and `loansOf` removed. `BUYBACK_HOOK`, `LOANS`, `DEFAULT_BUYBACK_POOL_FEE`, `DEFAULT_BUYBACK_TWAP_WINDOW`, `burnHeldTokensOf` added. `BurnHeldTokens` event added, `SetAdditionalOperator` event removed. `DeployRevnet` event lost `buybackHookConfiguration` param. NatSpec added. |
|
|
393
|
-
| `IREVLoans` | `IREVLoans` | `REVNETS` removed. `numberOfLoansFor` renamed to `totalLoansBorrowedFor`. `reallocateCollateralFromLoan` no longer payable. Constructor takes `IJBController` + `IJBProjects` instead of `IREVDeployer`. `ReallocateCollateral` event typo fixed. NatSpec added. |
|
|
394
|
-
|
|
395
|
-
### Contracts
|
|
396
|
-
|
|
397
|
-
| v5 | v6 | Notes |
|
|
398
|
-
|----|----|-------|
|
|
399
|
-
| `REVDeployer` | `REVDeployer` | Buyback hook architecture changed from per-revnet mapping to immutable registry. Loans changed from per-revnet to single immutable. Deploy functions consolidated. Every revnet gets a 721 hook. 721 permission flags inverted. `beforePayRecordedWith` rewritten for split-aware weight scaling. `burnHeldTokensOf` added. Split operator gains 3 new default permissions (`SET_BUYBACK_HOOK`, `SET_ROUTER_TERMINAL`, `SET_TOKEN_METADATA`). Feeless beneficiary cashout routing skips fee for feeless addresses. |
|
|
400
|
-
| `REVLoans` | `REVLoans` | Deployer dependency removed. Terminal validation replaces deployer ownership check. `numberOfLoansFor` renamed. `reallocateCollateralFromLoan` not payable. Source mismatch, zero borrow, and nothing-to-repay checks added. BURN_TOKENS permission requirement documented via NatSpec (no runtime check). Cross-revnet liquidation guard prevents loan ID namespace overflow. Liquidation loop uses `continue` instead of `break`. Stale loan data cleaned up on liquidation. Decimal normalization and zero-price safety in `_totalBorrowedFrom`. Source fee payment wrapped in try-catch. Timestamp cast fixed from `uint40` to `uint48`. |
|
|
401
|
-
|
|
402
|
-
### Structs
|
|
403
|
-
|
|
404
|
-
| v5 | v6 | Notes |
|
|
405
|
-
|----|----|-------|
|
|
406
|
-
| `REVAutoIssuance` | `REVAutoIssuance` | Identical (lint comment added) |
|
|
407
|
-
| `REVBuybackHookConfig` | (removed) | Buyback hook is now an immutable on the deployer |
|
|
408
|
-
| `REVBuybackPoolConfig` | (removed) | Was used within `REVBuybackHookConfig` |
|
|
409
|
-
| (not present) | `REVBaseline721HookConfig` | New struct for revnet-specific 721 hook configuration |
|
|
410
|
-
| (not present) | `REV721TiersHookFlags` | New subset of `JB721TiersHookFlags` without `issueTokensForSplits` |
|
|
411
|
-
| `REVConfig` | `REVConfig` | Removed `loanSources` and `loans` fields |
|
|
412
|
-
| `REVCroptopAllowedPost` | `REVCroptopAllowedPost` | Added `maximumSplitPercent` field |
|
|
413
|
-
| `REVDeploy721TiersHookConfig` | `REVDeploy721TiersHookConfig` | `baseline721HookConfiguration` type changed. Boolean flags inverted from opt-in to opt-out. |
|
|
414
|
-
| `REVDescription` | `REVDescription` | Identical (lint comment added) |
|
|
415
|
-
| `REVLoan` | `REVLoan` | Identical (lint comment added) |
|
|
416
|
-
| `REVLoanSource` | `REVLoanSource` | Identical (lint comment added) |
|
|
417
|
-
| `REVStageConfig` | `REVStageConfig` | Identical (lint comment added) |
|
|
418
|
-
| `REVSuckerDeploymentConfig` | `REVSuckerDeploymentConfig` | Identical (lint comment added) |
|
|
419
|
-
|
|
420
|
-
> **Cross-repo impact**: Uses `nana-721-hook-v6` tier splits system for NFT payment routing. Uses `nana-buyback-hook-v6` registry for automatic pool configuration. `nana-omnichain-deployers-v6` implements a similar dual-hook composition pattern. `nana-fee-project-deployer-v6` removed its buyback/loan configuration in favor of the centralized approach here.
|