@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/ADMINISTRATION.md
CHANGED
|
@@ -2,6 +2,33 @@
|
|
|
2
2
|
|
|
3
3
|
Admin privileges and their scope in revnet-core-v6. Revnets are designed to be autonomous Juicebox projects with no traditional owner. This document covers what privileged operations exist, who can perform them, and -- critically -- what is intentionally made impossible.
|
|
4
4
|
|
|
5
|
+
## At A Glance
|
|
6
|
+
|
|
7
|
+
| Item | Details |
|
|
8
|
+
|------|---------|
|
|
9
|
+
| Scope | Autonomous revnet deployment, split-operator powers, loan metadata ownership, and the boundaries imposed by revnet immutability. |
|
|
10
|
+
| Operators | The per-revnet split operator, the global `REVLoans` owner for metadata cosmetics, the protocol-owned `REVDeployer`, loan NFT holders, and permissionless callers for open lifecycle actions. |
|
|
11
|
+
| Highest-risk actions | Converting an existing project into a revnet, changing or burning the split operator, and configuring buyback, router, price-feed, or sucker permissions inside the narrow allowed operator surface. |
|
|
12
|
+
| Recovery posture | Revnet economics are intentionally not admin-recoverable. A bad deployment generally means abandoning the revnet and deploying a new one. |
|
|
13
|
+
|
|
14
|
+
## Routine Operations
|
|
15
|
+
|
|
16
|
+
- Use the split operator only for the limited post-launch surfaces the protocol deliberately leaves mutable: reserved-token split routing, selected hook metadata, router selection, and related operator-scoped settings.
|
|
17
|
+
- Keep `REVLoans` owner actions limited to URI resolver maintenance; that role should never be treated as an economic admin.
|
|
18
|
+
- Treat `deploySuckersFor`, buyback configuration, and router-terminal changes as operational extensions around a fixed revnet, not as tools to rewrite the revnet's stage economics.
|
|
19
|
+
- If autonomy is the goal, consider relinquishing the split operator to `address(0)` only after all intended mutable integrations are finalized.
|
|
20
|
+
|
|
21
|
+
## One-Way Or High-Risk Actions
|
|
22
|
+
|
|
23
|
+
- Deploying a revnet or converting an existing project into one is irreversible from an ownership and stage-design perspective.
|
|
24
|
+
- Setting the split operator to `address(0)` permanently burns the human-controlled role.
|
|
25
|
+
- Stage schedules, issuance curves, cash-out tax rates, and core economic parameters are fixed at deployment.
|
|
26
|
+
|
|
27
|
+
## Recovery Notes
|
|
28
|
+
|
|
29
|
+
- There is no admin escape hatch for broken revnet stage design. The recovery path is a new revnet deployment with corrected parameters.
|
|
30
|
+
- If an auxiliary integration such as a buyback hook or sucker is wrong but the split operator still has the relevant scoped power, fix that integration without expecting to change the underlying revnet economics.
|
|
31
|
+
|
|
5
32
|
## Roles
|
|
6
33
|
|
|
7
34
|
### Split Operator
|
package/ARCHITECTURE.md
CHANGED
|
@@ -1,149 +1,73 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Architecture
|
|
2
2
|
|
|
3
3
|
## Purpose
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
`revnet-core-v6` defines an autonomous Juicebox project pattern with staged, precommitted economics and token-collateralized loans. A revnet is intentionally ownerless after deployment: project behavior follows its queued stages and integrated hooks rather than ongoing governance.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Boundaries
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
├── REVLoans.sol — Borrow against burned revnet tokens (10-year max, permissionless liquidation)
|
|
14
|
-
├── interfaces/
|
|
15
|
-
│ ├── IREVDeployer.sol
|
|
16
|
-
│ ├── IREVOwner.sol
|
|
17
|
-
│ └── IREVLoans.sol
|
|
18
|
-
└── structs/ — REVConfig, REVStageConfig, REVLoanSource, REVAutoIssuance, etc.
|
|
19
|
-
```
|
|
9
|
+
- `REVDeployer` owns launch-time configuration and runtime wrapper behavior.
|
|
10
|
+
- `REVOwner` owns owner-like data-hook behavior for revnet projects.
|
|
11
|
+
- `REVLoans` owns the loan lifecycle.
|
|
12
|
+
- The repo composes several sibling repos instead of reimplementing them.
|
|
20
13
|
|
|
21
|
-
##
|
|
14
|
+
## Main Components
|
|
22
15
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
→ Auto-issuance: record per-beneficiary token counts for later claiming
|
|
30
|
-
→ Set REVOwner as data hook (controls pay + cashout behavior)
|
|
31
|
-
→ Initialize buyback pools at fair issuance price (derived from initialIssuance)
|
|
32
|
-
→ Deploy suckers for cross-chain operation
|
|
33
|
-
→ Deploy tiered ERC-721 hook (always — empty by default, pre-configured if specified)
|
|
34
|
-
→ Compute matching hash and store it for cross-chain sucker deployment
|
|
35
|
-
```
|
|
16
|
+
| Component | Responsibility |
|
|
17
|
+
| --- | --- |
|
|
18
|
+
| `REVDeployer` | Launches revnets, queues staged rulesets, wires hooks, grants operator permissions, and exposes runtime wrapper behavior |
|
|
19
|
+
| `REVOwner` | Ownerless policy surface plugged into revnet rulesets |
|
|
20
|
+
| `REVLoans` | Burn-collateral borrow/repay/liquidate flow represented as ERC-721 loans |
|
|
21
|
+
| config structs | Stage, auto-issuance, loan source, and 721-hook configuration surfaces |
|
|
36
22
|
|
|
37
|
-
|
|
23
|
+
## Runtime Model
|
|
38
24
|
|
|
39
|
-
|
|
25
|
+
### Revnet Lifecycle
|
|
40
26
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
27
|
+
```text
|
|
28
|
+
creator
|
|
29
|
+
-> deploys a revnet with a fixed sequence of stages
|
|
30
|
+
stage transitions
|
|
31
|
+
-> happen automatically over time through ruleset activation
|
|
32
|
+
participants
|
|
33
|
+
-> pay in, receive tokens, cash out, and interact with downstream hooks
|
|
34
|
+
operators or permissionless callers
|
|
35
|
+
-> perform bounded maintenance actions such as auto-issuance claims
|
|
36
|
+
```
|
|
47
37
|
|
|
48
|
-
|
|
38
|
+
### Loan Lifecycle
|
|
49
39
|
|
|
50
|
-
|
|
40
|
+
```text
|
|
41
|
+
borrower
|
|
42
|
+
-> burns revnet tokens as collateral
|
|
43
|
+
-> receives funds from the treasury through REVLoans
|
|
44
|
+
-> later repays to remint collateral
|
|
45
|
+
-> or gets liquidated after the long expiration window
|
|
46
|
+
```
|
|
51
47
|
|
|
52
|
-
|
|
48
|
+
## Critical Invariants
|
|
53
49
|
|
|
54
|
-
|
|
50
|
+
- The project is designed to be ownerless after deployment. "Easy" admin recovery paths would break the product thesis.
|
|
51
|
+
- Stage configuration is effectively permanent once queued.
|
|
52
|
+
- Loan collateral is burned, not escrowed. Supply-sensitive logic must treat that as real destruction until repayment.
|
|
53
|
+
- `REVOwner` and `REVDeployer` are tightly coupled. Their setup order is part of correctness.
|
|
55
54
|
|
|
56
|
-
|
|
55
|
+
## Where Complexity Lives
|
|
57
56
|
|
|
58
|
-
|
|
57
|
+
- Revnets span deployment-time guarantees, runtime hook behavior, and loan-state transitions.
|
|
58
|
+
- The most subtle risks sit where treasury state, stage economics, and loan borrowability interact.
|
|
59
|
+
- Ownerlessness is a feature, but it also removes easy operational recovery from misconfiguration.
|
|
59
60
|
|
|
60
|
-
|
|
61
|
-
```
|
|
62
|
-
Payment → REVOwner.beforePayRecordedWith()
|
|
63
|
-
→ Read tiered721HookOf from REVOwner storage
|
|
64
|
-
→ Query 721 tier hook for tier split specs (if configured)
|
|
65
|
-
→ Delegate remaining amount to buyback hook for swap-vs-mint decision
|
|
66
|
-
→ Scale weight so tokens are only minted for the project's share (after tier splits)
|
|
67
|
-
→ Return merged hook specifications (721 hook + buyback hook)
|
|
68
|
-
|
|
69
|
-
Cash Out → REVOwner.beforeCashOutRecordedWith()
|
|
70
|
-
→ If caller is a sucker: 0% cash out tax, full reclaim (bridging privilege)
|
|
71
|
-
→ Enforce cash out delay (reads cashOutDelayOf from REVOwner storage)
|
|
72
|
-
→ If no tax, no fee terminal, or feeless beneficiary: delegate directly to buyback hook
|
|
73
|
-
→ Otherwise: split tokens into fee/non-fee portions via bonding curve
|
|
74
|
-
→ Delegate non-fee portion to buyback hook
|
|
75
|
-
→ Build fee hook spec routing fee amount to afterCashOutRecordedWith for processing
|
|
76
|
-
→ Return merged hook specifications (buyback hook + fee hook)
|
|
77
|
-
```
|
|
61
|
+
## Dependencies
|
|
78
62
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
→ Enforce cash-out delay if set (cross-chain deployment protection)
|
|
83
|
-
→ Burn borrower's revnet tokens as collateral
|
|
84
|
-
→ Calculate borrow amount from bonding curve value of collateral
|
|
85
|
-
→ Pull funds from treasury via USE_ALLOWANCE
|
|
86
|
-
→ Mint loan ERC-721 NFT to borrower
|
|
87
|
-
|
|
88
|
-
Repay → REVLoans.repayLoan()
|
|
89
|
-
→ Accept repayment (principal + prepaid fee)
|
|
90
|
-
→ Re-mint collateral tokens to borrower
|
|
91
|
-
|
|
92
|
-
Liquidate → REVLoans.liquidateExpiredLoansFrom()
|
|
93
|
-
→ After 10-year term, anyone can liquidate
|
|
94
|
-
→ Collateral permanently destroyed (was burned at borrow time)
|
|
95
|
-
```
|
|
63
|
+
- `nana-core-v6` for treasury and ruleset mechanics
|
|
64
|
+
- `nana-buyback-hook-v6`, `nana-suckers-v6`, `nana-router-terminal-v6`, and optionally `nana-721-hook-v6` for composed features
|
|
65
|
+
- `croptop-core-v6` and other product repos when revnets are used as economic backends
|
|
96
66
|
|
|
97
|
-
##
|
|
98
|
-
|
|
99
|
-
Each `REVStageConfig` is converted to a `JBRulesetConfig` by `_makeRulesetConfiguration`. The mapping is direct — revnet stages are a constrained interface over Juicebox rulesets:
|
|
100
|
-
|
|
101
|
-
| REVStageConfig field | JBRulesetConfig field | Notes |
|
|
102
|
-
|---|---|---|
|
|
103
|
-
| `startsAtOrAfter` | `mustStartAtOrAfter` | Passed through directly |
|
|
104
|
-
| `issuanceCutFrequency` | `duration` | How often the issuance rate decays |
|
|
105
|
-
| `initialIssuance` | `weight` | Tokens per unit of base currency |
|
|
106
|
-
| `issuanceCutPercent` | `weightCutPercent` | Percent decrease each cycle (out of 1,000,000,000) |
|
|
107
|
-
| `splitPercent` | `metadata.reservedPercent` | Percent of new tokens split to recipients (out of 10,000) |
|
|
108
|
-
| `cashOutTaxRate` | `metadata.cashOutTaxRate` | Bonding curve tax on cash outs (out of 10,000) |
|
|
109
|
-
| `splits` | `splitGroups[0].splits` | Reserved token split recipients (group ID: RESERVED_TOKENS) |
|
|
110
|
-
| `extraMetadata` | `metadata.metadata` | 14-bit field for hook-specific flags |
|
|
111
|
-
|
|
112
|
-
Fields set automatically by the deployer (not configurable per stage):
|
|
113
|
-
- `metadata.baseCurrency` — from `REVConfig.baseCurrency`
|
|
114
|
-
- `metadata.useTotalSurplusForCashOuts` — always `true`
|
|
115
|
-
- `metadata.allowOwnerMinting` — always `true` (required for auto-issuance)
|
|
116
|
-
- `metadata.useDataHookForPay` — always `true`
|
|
117
|
-
- `metadata.useDataHookForCashOut` — always `true`
|
|
118
|
-
- `metadata.dataHook` — always `address(REVOwner)`
|
|
119
|
-
- `approvalHook` — always `address(0)` (no approval hook; stages are immutable)
|
|
120
|
-
- `fundAccessLimitGroups` — set to `uint224.max` surplus allowance per terminal token for loan withdrawals
|
|
121
|
-
|
|
122
|
-
## Extension Points
|
|
123
|
-
|
|
124
|
-
| Point | Interface | Purpose |
|
|
125
|
-
|-------|-----------|---------|
|
|
126
|
-
| Data hook | `IJBRulesetDataHook` | REVOwner acts as data hook for all revnets |
|
|
127
|
-
| Buyback hook | `IJBBuybackHook` | Swap-vs-mint decision on payments |
|
|
128
|
-
| Sucker integration | `IJBSucker` | Cross-chain token bridging |
|
|
129
|
-
| 721 tiers | `IJB721TiersHook` | NFT tier rewards |
|
|
67
|
+
## Safe Change Guide
|
|
130
68
|
|
|
131
|
-
|
|
132
|
-
-
|
|
133
|
-
-
|
|
134
|
-
-
|
|
135
|
-
-
|
|
136
|
-
- `@bananapus/router-terminal-v6` — Payment routing
|
|
137
|
-
- `@bananapus/permission-ids-v6` — Permission constants
|
|
138
|
-
- `@croptop/core-v6` — Croptop integration
|
|
139
|
-
- `@openzeppelin/contracts` — Standard utilities
|
|
140
|
-
- `@prb/math` — Fixed-point math (`mulDiv`, `sqrt`)
|
|
141
|
-
- `@uniswap/permit2` — Permit2 token allowances (REVLoans)
|
|
142
|
-
|
|
143
|
-
## Key Design Decisions
|
|
144
|
-
- Stages are immutable after deployment — no owner can change ruleset parameters
|
|
145
|
-
- Matching hash ensures cross-chain deployments have identical economic parameters. It covers all economic fields (issuance, decay, tax rates, auto-issuances) but intentionally excludes split recipient addresses, which may differ by chain. The hash is used as a CREATE2 salt component for sucker deployment, so mismatched configs produce different sucker addresses that cannot peer with each other.
|
|
146
|
-
- REVOwner is the data hook for all revnets — centralizes runtime behavioral control (pay hooks, cash-out hooks, mint permissions) and stores `cashOutDelayOf` and `tiered721HookOf` per revnet. REVDeployer handles deployment and configuration state storage. The split was necessary to stay under the EIP-170 contract size limit (24,576 bytes). Deploy order: REVOwner first, then REVDeployer(owner=REVOwner) -- the constructor calls `REVOwner.setDeployer()` atomically. REVDeployer calls DEPLOYER-restricted setters on REVOwner (`setCashOutDelayOf`, `setTiered721HookOf`) during deployment.
|
|
147
|
-
- Loans use bonding curve value, not market price — independent of external DEX pricing
|
|
148
|
-
- Auto-issuance is deferred, not instant — token amounts are recorded at deploy time but minted via a separate `autoIssueFor` call after the stage starts. This separates deployment from issuance, allows anyone to trigger the mint permissionlessly, and ensures tokens are not minted before their stage is active.
|
|
149
|
-
- No approval hook — revnet rulesets set `approvalHook` to `address(0)` because stages are configured immutably at deployment. There is no governance or owner who could queue a change that would need approval.
|
|
69
|
+
- Treat deployer-time behavior and runtime wrapper behavior as one system.
|
|
70
|
+
- Any change to stage semantics should be checked against loan math, cash-out semantics, and downstream fee-project expectations.
|
|
71
|
+
- Do not casually add mutable admin escape hatches.
|
|
72
|
+
- Flash-loan and surplus-sensitive logic deserves adversarial review whenever loan calculations change.
|
|
73
|
+
- If a change affects borrowability or repayment, test both sourced and unsourced loan paths.
|