@rev-net/core-v6 0.0.23 → 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 -6
- package/test/TestSplitWeightFork.t.sol +10 -6
- package/test/fork/ForkTestBase.sol +10 -6
- package/CHANGE_LOG.md +0 -420
package/README.md
CHANGED
|
@@ -1,110 +1,74 @@
|
|
|
1
1
|
# Revnet Core
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`@rev-net/core-v6` deploys and operates Revnets: autonomous Juicebox projects with staged economics, optional tiered NFTs, cross-chain support, buyback integration, and token-collateralized loans.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Docs: <https://docs.juicebox.money>
|
|
6
|
+
Architecture: [ARCHITECTURE.md](./ARCHITECTURE.md)
|
|
6
7
|
|
|
7
|
-
##
|
|
8
|
+
## Overview
|
|
8
9
|
|
|
9
|
-
A Revnet is
|
|
10
|
+
A Revnet is meant to run without a human owner after launch. Its economics are encoded up front as a sequence of stages, and the runtime hook plus loan system enforce those rules over time.
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
This package provides:
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
- a deployer that launches Revnets and stores their long-lived configuration
|
|
15
|
+
- a runtime hook that mediates pay, cash-out, mint-permission, and delayed-cash-out behavior
|
|
16
|
+
- an ERC-721 loan system that burns token collateral on borrow and remints on repayment
|
|
14
17
|
|
|
15
|
-
|
|
18
|
+
It also composes with the 721 hook stack, buyback hook, router terminal, Croptop, and suckers where needed.
|
|
16
19
|
|
|
17
|
-
|
|
18
|
-
1. Deploy revnet with stage configurations
|
|
19
|
-
→ REVDeployer.deployFor(revnetId=0, config, terminals, suckerConfig)
|
|
20
|
-
→ Creates Juicebox project owned by REVDeployer (permanently), dataHook = REVOwner
|
|
21
|
-
→ Deploys ERC-20 token, initializes buyback pools at 1:1 price, deploys suckers
|
|
22
|
-
|
|
|
23
|
-
2. Stage 1 begins (startsAtOrAfter or block.timestamp)
|
|
24
|
-
→ Tokens issued at initialIssuance rate per unit of base currency
|
|
25
|
-
→ Issuance decays by issuanceCutPercent every issuanceCutFrequency
|
|
26
|
-
→ splitPercent of new tokens go to reserved splits
|
|
27
|
-
→ Cash outs taxed at cashOutTaxRate (2.5% fee to fee revnet)
|
|
28
|
-
|
|
|
29
|
-
3. Stage transitions happen automatically
|
|
30
|
-
→ When startsAtOrAfter timestamp is reached for next stage
|
|
31
|
-
→ New issuance rate, tax rate, splits, etc. take effect
|
|
32
|
-
→ No governance, no votes, no owner action required
|
|
33
|
-
|
|
|
34
|
-
4. Participants can borrow against their tokens
|
|
35
|
-
→ REVLoans.borrowFrom(revnetId, source, collateral, ...)
|
|
36
|
-
→ Collateral tokens are burned, funds pulled from treasury
|
|
37
|
-
→ Loan is an ERC-721 NFT, liquidates after 10 years
|
|
38
|
-
|
|
|
39
|
-
5. Ongoing operations (permissionless or split operator)
|
|
40
|
-
→ Auto-issuance claims (permissionless)
|
|
41
|
-
→ Buyback pool configuration (split operator)
|
|
42
|
-
→ Sucker deployment (split operator, if ruleset allows)
|
|
43
|
-
→ Split group updates (split operator)
|
|
44
|
-
```
|
|
20
|
+
Use this repo when the product is an autonomous treasury-backed network with encoded stage transitions. Do not use it when governance, mutable operator control, or simple project deployment is the goal.
|
|
45
21
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
```mermaid
|
|
58
|
-
sequenceDiagram
|
|
59
|
-
participant Borrower
|
|
60
|
-
participant REVLoans
|
|
61
|
-
participant JBController
|
|
62
|
-
participant JBMultiTerminal
|
|
63
|
-
participant Beneficiary
|
|
64
|
-
|
|
65
|
-
Note over Borrower,Beneficiary: Borrow
|
|
66
|
-
Borrower->>REVLoans: borrowFrom(revnetId, source, collateral, ...)
|
|
67
|
-
REVLoans->>JBController: burnTokensOf(borrower, collateral)
|
|
68
|
-
REVLoans->>JBMultiTerminal: useAllowanceOf(revnetId, borrowAmount)
|
|
69
|
-
JBMultiTerminal-->>REVLoans: net funds (minus protocol fee)
|
|
70
|
-
REVLoans-->>Beneficiary: borrowed funds (minus prepaid fee)
|
|
71
|
-
REVLoans-->>Borrower: mint loan ERC-721 NFT
|
|
72
|
-
|
|
73
|
-
Note over Borrower,Beneficiary: Repay
|
|
74
|
-
Borrower->>REVLoans: repayLoan(loanId, collateralToReturn, ...)
|
|
75
|
-
REVLoans->>REVLoans: burn loan ERC-721 NFT
|
|
76
|
-
REVLoans->>JBMultiTerminal: addToBalanceOf(revnetId, repayAmount)
|
|
77
|
-
REVLoans->>JBController: mintTokensOf(beneficiary, collateral)
|
|
78
|
-
Note right of Beneficiary: Collateral tokens re-minted
|
|
79
|
-
```
|
|
22
|
+
The key point is that a Revnet is not just "a Juicebox project with presets." It is a project shape whose admin surface is intentionally collapsed into deployment-time configuration plus constrained runtime operators.
|
|
23
|
+
|
|
24
|
+
## Key Contracts
|
|
25
|
+
|
|
26
|
+
| Contract | Role |
|
|
27
|
+
| --- | --- |
|
|
28
|
+
| `REVDeployer` | Launches and configures Revnets, stages, split operators, and optional auxiliary features. |
|
|
29
|
+
| `REVOwner` | Runtime data-hook and cash-out-hook surface used by active Revnets. |
|
|
30
|
+
| `REVLoans` | Loan surface that lets users borrow against Revnet tokens with burned collateral and NFT loan positions. |
|
|
31
|
+
|
|
32
|
+
## Mental Model
|
|
80
33
|
|
|
81
|
-
|
|
34
|
+
Read the package in two halves:
|
|
82
35
|
|
|
83
|
-
|
|
36
|
+
1. deployment-time shape: `REVDeployer` decides what the network will be allowed to do
|
|
37
|
+
2. runtime enforcement: `REVOwner` and `REVLoans` decide how that shape behaves over time
|
|
84
38
|
|
|
85
|
-
|
|
86
|
-
- **Tiered 721 revnet** -- `deployFor` adds a tiered 721 pay hook with pre-configured tiers that mint NFTs as people pay. Choose this when the revnet should sell specific NFT tiers from day one, such as membership passes or limited editions.
|
|
87
|
-
- **Croptop revnet** -- A tiered 721 revnet with Croptop posting criteria, allowing the public to post content. Choose this when the revnet should function as an open publishing platform where anyone can submit content that gets minted as NFTs according to the configured posting rules.
|
|
39
|
+
That split matters because most mistakes are one of these:
|
|
88
40
|
|
|
89
|
-
|
|
41
|
+
- assuming a deploy-time parameter can be changed later
|
|
42
|
+
- assuming a runtime hook is only advisory rather than economically binding
|
|
90
43
|
|
|
91
|
-
|
|
92
|
-
|----------|-------------|
|
|
93
|
-
| `REVDeployer` | Deploys revnets as Juicebox projects owned by the deployer contract itself (no human owner). Translates stage configurations into Juicebox rulesets, manages buyback hooks, suckers, split operators, auto-issuance, and configuration state storage. Handles deployment, configuration, and split operator management. Calls DEPLOYER-restricted setters on REVOwner during deployment to store `cashOutDelayOf` and `tiered721HookOf`. |
|
|
94
|
-
| `REVOwner` | Runtime hook contract for all revnets. Implements `IJBRulesetDataHook` and `IJBCashOutHook`. Set as the `dataHook` in each revnet's ruleset metadata. Handles `beforePayRecordedWith`, `beforeCashOutRecordedWith`, `afterCashOutRecordedWith`, `hasMintPermissionFor`, and sucker verification. When 721 tier splits are active, adjusts the payment weight so the terminal only mints tokens proportional to the amount entering the project treasury (the split portion is forwarded separately). Stores `cashOutDelayOf` and `tiered721HookOf` mappings (set by REVDeployer via DEPLOYER-restricted setters `setCashOutDelayOf()` and `setTiered721HookOf()`). |
|
|
95
|
-
| `REVLoans` | Lets participants borrow against their revnet tokens. Collateral tokens are burned on borrow and re-minted on repayment. Each loan is an ERC-721 NFT. Charges a prepaid fee (2.5% min, 50% max) that determines the interest-free duration; after that window, a time-proportional source fee accrues. Loans liquidate after 10 years. |
|
|
44
|
+
The shortest useful reading order is:
|
|
96
45
|
|
|
97
|
-
|
|
46
|
+
1. `REVDeployer`
|
|
47
|
+
2. `REVOwner`
|
|
48
|
+
3. `REVLoans`
|
|
49
|
+
4. any integrated hook or bridge repo the deployment enables
|
|
98
50
|
|
|
99
|
-
|
|
51
|
+
## Read These Files First
|
|
100
52
|
|
|
101
|
-
|
|
53
|
+
1. `src/REVDeployer.sol`
|
|
54
|
+
2. `src/REVOwner.sol`
|
|
55
|
+
3. `src/REVLoans.sol`
|
|
56
|
+
4. the integrated hook or bridge repo used by the deployment
|
|
102
57
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
58
|
+
## Integration Traps
|
|
59
|
+
|
|
60
|
+
- the deployer holding the project NFT is not an implementation detail; it is part of the ownership model
|
|
61
|
+
- split operators are constrained, not equivalent to general protocol governance
|
|
62
|
+
- the loan system depends on live revnet economics, so it should be reviewed together with the runtime hook and treasury assumptions
|
|
63
|
+
- optional integrations like buybacks, 721 hooks, and suckers are compositional, but they materially change the resulting network
|
|
64
|
+
|
|
65
|
+
## Where State Lives
|
|
66
|
+
|
|
67
|
+
- deployment-time configuration and operator envelope live in `REVDeployer`
|
|
68
|
+
- runtime pay and cash-out behavior live in `REVOwner`
|
|
69
|
+
- loan positions and loan-specific state live in `REVLoans`
|
|
70
|
+
|
|
71
|
+
Do not audit those contracts in isolation if the deployment enables cross-package features; the composed network is the real product.
|
|
108
72
|
|
|
109
73
|
## Install
|
|
110
74
|
|
|
@@ -112,109 +76,46 @@ Every revnet gets a tiered ERC-721 hook deployed automatically — even if no ti
|
|
|
112
76
|
npm install @rev-net/core-v6
|
|
113
77
|
```
|
|
114
78
|
|
|
115
|
-
|
|
79
|
+
## Development
|
|
116
80
|
|
|
117
81
|
```bash
|
|
118
|
-
npm install
|
|
82
|
+
npm install
|
|
83
|
+
forge build
|
|
84
|
+
forge test
|
|
119
85
|
```
|
|
120
86
|
|
|
121
|
-
|
|
87
|
+
Useful scripts:
|
|
88
|
+
|
|
89
|
+
- `npm run deploy:mainnets`
|
|
90
|
+
- `npm run deploy:testnets`
|
|
91
|
+
- `npm run deploy:mainnets:1_1`
|
|
92
|
+
- `npm run deploy:testnets:1_1`
|
|
122
93
|
|
|
123
|
-
##
|
|
94
|
+
## Deployment Notes
|
|
124
95
|
|
|
125
|
-
|
|
126
|
-
|---------|-------------|
|
|
127
|
-
| `forge build` | Compile contracts |
|
|
128
|
-
| `forge test` | Run tests (55 test files covering deployment, lifecycle, loans, attacks, invariants, fork tests, regressions) |
|
|
129
|
-
| `forge test -vvvv` | Run tests with full traces |
|
|
96
|
+
Revnet deployment assumes the core protocol, 721 hook, buyback hook, router terminal, suckers, and Croptop packages are available. Every Revnet is intentionally unowned after deployment in the human sense; the deployer contract itself retains the project NFT.
|
|
130
97
|
|
|
131
98
|
## Repository Layout
|
|
132
99
|
|
|
133
|
-
```
|
|
100
|
+
```text
|
|
134
101
|
src/
|
|
135
|
-
REVDeployer.sol
|
|
136
|
-
REVOwner.sol
|
|
137
|
-
REVLoans.sol
|
|
102
|
+
REVDeployer.sol
|
|
103
|
+
REVOwner.sol
|
|
104
|
+
REVLoans.sol
|
|
138
105
|
interfaces/
|
|
139
|
-
IREVDeployer.sol # Deployer interface + events
|
|
140
|
-
IREVOwner.sol # Owner interface (cashOutDelayOf view)
|
|
141
|
-
IREVLoans.sol # Loans interface + events
|
|
142
106
|
structs/
|
|
143
|
-
REVConfig.sol # Top-level deployment config
|
|
144
|
-
REVDescription.sol # ERC-20 metadata (name, ticker, uri, salt)
|
|
145
|
-
REVStageConfig.sol # Economic stage parameters
|
|
146
|
-
REVAutoIssuance.sol # Per-stage cross-chain premint
|
|
147
|
-
REVLoan.sol # Loan state
|
|
148
|
-
REVLoanSource.sol # Terminal + token pair for loans
|
|
149
|
-
REVBaseline721HookConfig.sol # 721 hook config (omits issueTokensForSplits)
|
|
150
|
-
REV721TiersHookFlags.sol # 721 hook flags for revnets (no issueTokensForSplits)
|
|
151
|
-
REVDeploy721TiersHookConfig.sol # 721 hook deployment config wrapper
|
|
152
|
-
REVCroptopAllowedPost.sol # Croptop posting criteria
|
|
153
|
-
REVSuckerDeploymentConfig.sol # Cross-chain sucker deployment
|
|
154
107
|
test/
|
|
155
|
-
|
|
156
|
-
REVLifecycle.t.sol # Stage transitions, weight decay
|
|
157
|
-
REVAutoIssuanceFuzz.t.sol # Auto-issuance fuzz tests
|
|
158
|
-
REVInvincibility.t.sol # Economic property fuzzing
|
|
159
|
-
REVInvincibilityHandler.sol # Fuzz handler
|
|
160
|
-
REVDeployerRegressions.t.sol # Deployer regressions
|
|
161
|
-
REVLoansSourced.t.sol # Multi-source loan tests
|
|
162
|
-
REVLoansUnSourced.t.sol # Loan error cases
|
|
163
|
-
REVLoansFeeRecovery.t.sol # Fee calculation tests
|
|
164
|
-
REVLoansAttacks.t.sol # Flash loan, reentrancy scenarios
|
|
165
|
-
REVLoans.invariants.t.sol # Loan fuzzing invariants
|
|
166
|
-
REVLoansRegressions.t.sol # Loan regressions
|
|
167
|
-
helpers/
|
|
168
|
-
MaliciousContracts.sol # Attack contract mocks
|
|
169
|
-
mock/
|
|
170
|
-
MockBuybackDataHook.sol # Mock for buyback hook tests
|
|
108
|
+
lifecycle, deployment, loan, fork, invariant, audit, and regression coverage
|
|
171
109
|
script/
|
|
172
|
-
Deploy.s.sol
|
|
110
|
+
Deploy.s.sol
|
|
173
111
|
helpers/
|
|
174
|
-
RevnetCoreDeploymentLib.sol # Deployment artifact reader
|
|
175
112
|
```
|
|
176
113
|
|
|
177
|
-
##
|
|
178
|
-
|
|
179
|
-
### Split Operator (per-revnet)
|
|
180
|
-
|
|
181
|
-
The split operator has these default permissions:
|
|
182
|
-
|
|
183
|
-
| Permission | Purpose |
|
|
184
|
-
|------------|---------|
|
|
185
|
-
| `SET_SPLIT_GROUPS` | Change reserved token splits |
|
|
186
|
-
| `SET_BUYBACK_POOL` | Configure Uniswap buyback pool |
|
|
187
|
-
| `SET_BUYBACK_TWAP` | Adjust TWAP window for buyback |
|
|
188
|
-
| `SET_PROJECT_URI` | Update project metadata |
|
|
189
|
-
| `ADD_PRICE_FEED` | Add price oracle |
|
|
190
|
-
| `SUCKER_SAFETY` | Emergency sucker functions |
|
|
191
|
-
| `SET_BUYBACK_HOOK` | Swap buyback hook |
|
|
192
|
-
| `SET_ROUTER_TERMINAL` | Swap terminal |
|
|
193
|
-
| `SET_TOKEN_METADATA` | Update token name and symbol |
|
|
194
|
-
|
|
195
|
-
Plus optional from 721 hook config: `ADJUST_721_TIERS`, `SET_721_METADATA`, `MINT_721`, `SET_721_DISCOUNT_PERCENT`.
|
|
196
|
-
|
|
197
|
-
### Global Permissions
|
|
198
|
-
|
|
199
|
-
| Grantee | Permission | Scope |
|
|
200
|
-
|---------|------------|-------|
|
|
201
|
-
| `SUCKER_REGISTRY` | `MAP_SUCKER_TOKEN` | All revnets (wildcard projectId=0) |
|
|
202
|
-
| `REVLoans` | `USE_ALLOWANCE` | All revnets (wildcard projectId=0) |
|
|
203
|
-
|
|
204
|
-
### Permissionless Operations
|
|
205
|
-
|
|
206
|
-
- `autoIssueFor` -- claim auto-issuance tokens (anyone)
|
|
207
|
-
- `burnHeldTokensOf` -- burn reserved tokens held by deployer (anyone)
|
|
114
|
+
## Risks And Notes
|
|
208
115
|
|
|
209
|
-
|
|
116
|
+
- Revnets are intentionally hard to change after launch, so bad stage design is expensive
|
|
117
|
+
- `REVLoans` relies on live treasury conditions and is therefore sensitive to surplus and pricing assumptions
|
|
118
|
+
- the deployer and runtime hook have a tight relationship that should be treated as one design, not two independent contracts
|
|
119
|
+
- burned-collateral lending is operationally different from escrowed-collateral lending and needs clear integrator expectations
|
|
210
120
|
|
|
211
|
-
|
|
212
|
-
- **REVOwner circular dependency.** REVOwner and REVDeployer have a circular dependency broken by `setDeployer()`, called atomically from REVDeployer's constructor. `REVOwner.DEPLOYER` is a storage variable (not immutable). `setDeployer()` sets `msg.sender` as `DEPLOYER` and reverts if already set. If `setDeployer()` is never called, the DEPLOYER-restricted setters (`setCashOutDelayOf`, `setTiered721HookOf`) cannot be called correctly, and all runtime hook behavior breaks.
|
|
213
|
-
- **Loan flash-loan exposure.** `borrowableAmountFrom` reads live surplus, which can be inflated via flash loans. A borrower could temporarily inflate the treasury to borrow more than the sustained value would support.
|
|
214
|
-
- **uint112 truncation.** `REVLoan.amount` and `REVLoan.collateral` are `uint112` -- values above ~5.19e33 truncate silently.
|
|
215
|
-
- **Cash-out fee stacking.** Cash outs incur both the Juicebox terminal fee (2.5%) and the revnet cash-out fee (2.5% to fee revnet). These compound.
|
|
216
|
-
- **Auto-issuance stage IDs.** Stage IDs are `block.timestamp + i` during deployment. These match the Juicebox ruleset IDs because `JBRulesets` assigns IDs the same way (`latestId >= block.timestamp ? latestId + 1 : block.timestamp`), producing identical sequential IDs when all stages are queued in a single `deployFor()` call.
|
|
217
|
-
- **NATIVE_TOKEN on non-ETH chains.** Using `JBConstants.NATIVE_TOKEN` on Celo or Polygon means CELO/MATIC, not ETH. Use ERC-20 WETH instead. The matching hash does NOT catch this -- it covers economic parameters but NOT terminal configurations.
|
|
218
|
-
- **30-day cash-out delay.** When deploying an existing revnet to a new chain where the first stage has already started, a 30-day delay is imposed before cash outs are allowed, preventing cross-chain liquidity arbitrage.
|
|
219
|
-
- **Loan source array growth.** `_loanSourcesOf[revnetId]` is unbounded. If an attacker creates loans from many different terminals/tokens, the array grows without limit.
|
|
220
|
-
- **10-year loan liquidation.** Expired loans (10+ years) can be liquidated by anyone. The burned collateral is permanently lost -- it was destroyed at borrow time.
|
|
121
|
+
The usual review failure mode is to focus on the loans or the stages in isolation. The real system is the combination of stage economics, runtime hook behavior, and who is still allowed to act after deployment.
|
package/RISKS.md
CHANGED
|
@@ -1,10 +1,22 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Revnet Core Risk Register
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This file focuses on the risks created by autonomous treasury-backed projects with staged economics, composable hooks, cross-chain wiring, and token-collateralized loans.
|
|
4
4
|
|
|
5
5
|
Read [ARCHITECTURE.md](./ARCHITECTURE.md) and [SKILLS.md](./SKILLS.md) for protocol context first.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## How to use this file
|
|
8
|
+
|
|
9
|
+
- Read `Priority risks` first; they capture the highest-impact ways a revnet can misprice, misroute, or mis-govern itself.
|
|
10
|
+
- Use the detailed sections for economics, loans, data-hook proxying, and liveness reasoning.
|
|
11
|
+
- Treat `Accepted Behaviors` and `Invariants to Verify` as the operating contract for revnet deployments.
|
|
12
|
+
|
|
13
|
+
## Priority risks
|
|
14
|
+
|
|
15
|
+
| Priority | Risk | Why it matters | Primary controls |
|
|
16
|
+
|----------|------|----------------|------------------|
|
|
17
|
+
| P0 | Loan mispricing from bad surplus or configuration | `REVLoans` depends on correct surplus, fee, and deployer-owned configuration; bad inputs can enable over-borrowing. | Surplus and price checks, deployer verification, and loan-specific invariant coverage. |
|
|
18
|
+
| P0 | Deployer or data-hook proxy blast radius | `REVDeployer` sits in the pay and cash-out path for all revnets it launched. A bug here affects every attached project. | High-scrutiny review, composition testing, and cautious shared-deployer usage. |
|
|
19
|
+
| P1 | Stage or split misconfiguration becomes permanent | Revnets are intentionally autonomous and hard to govern after launch; bad initial economics are difficult or impossible to fix. | Strong pre-launch review, deployment runbooks, and config simulation before production. |
|
|
8
20
|
|
|
9
21
|
## 1. Trust Assumptions
|
|
10
22
|
|
|
@@ -40,7 +52,7 @@ Read [ARCHITECTURE.md](./ARCHITECTURE.md) and [SKILLS.md](./SKILLS.md) for proto
|
|
|
40
52
|
|
|
41
53
|
- **`cashOutTaxRate` increase destroys loan health.** Active loans use the CURRENT stage's `cashOutTaxRate`. When a stage transition increases this rate, existing loans become under-collateralized -- the collateral's cash-out value drops but the loan amount remains unchanged. No forced repayment or margin call mechanism exists. Over 10 years with multiple stage transitions, this compounds.
|
|
42
54
|
- **`cashOutTaxRate` decrease creates refinancing opportunity.** When a new stage lowers the tax rate, existing collateral becomes worth more. Borrowers can `reallocateCollateralFromLoan` to extract the surplus value. This creates a predictable, front-runnable event at every stage boundary.
|
|
43
|
-
- **Weight decay approaching zero over long periods.** With `issuanceCutPercent > 0` and `issuanceCutFrequency > 0`, issuance weight decays exponentially. After
|
|
55
|
+
- **Weight decay approaching zero over long periods.** With `issuanceCutPercent > 0` and `issuanceCutFrequency > 0`, issuance weight decays exponentially through successive rulesets. After long enough, new payments mint negligibly few tokens, meaning the token supply effectively freezes. This concentrates cash-out value among existing holders and makes the bonding curve increasingly sensitive to individual cash-outs. The current repo models decay through ruleset duration and `weightCutPercent`, so validation should focus on long-horizon ruleset progression and issuance-decay tests rather than any separate weight-cache updater.
|
|
44
56
|
- **Duration=0 stages never auto-expire.** A stage with `duration=0` (no issuance cut frequency) persists until explicitly replaced by a subsequent stage's `startsAtOrAfter`. If the next stage's `startsAtOrAfter` is far in the future, the current stage runs indefinitely at its configured parameters.
|
|
45
57
|
|
|
46
58
|
### Cross-currency reclaim calculations
|