@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 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
- # revnet-core-v6 — Architecture
1
+ # Architecture
2
2
 
3
3
  ## Purpose
4
4
 
5
- Autonomous revenue networks ("revnets") built on Juicebox V6. REVDeployer creates projects with pre-programmed multi-stage rulesets that cannot be changed after deployment. REVOwner handles all runtime hook behavior (pay hooks, cash-out hooks, mint permissions) as the `dataHook` for every revnet. REVLoans enables borrowing against locked revnet tokens.
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
- ## Contract Map
7
+ ## Boundaries
8
8
 
9
- ```
10
- src/
11
- ├── REVDeployer.sol — Deploys revnets: stages → rulesets, buyback, suckers, 721 tiers, state storage
12
- ├── REVOwner.sol — Runtime data hook + cash-out hook for all revnets, stores cashOutDelayOf + tiered721HookOf (~310 lines)
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
- ## Key Data Flows
14
+ ## Main Components
22
15
 
23
- ### Revnet Deployment
24
- ```
25
- Deployer REVDeployer.deployFor()
26
- Create JB project via JBController
27
- Convert REV stages JBRulesetConfigs (see Stage-to-Ruleset Mapping below)
28
- Each stage: duration, weight, cashOutTaxRate, splits
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
- #### Matching Hash
23
+ ## Runtime Model
38
24
 
39
- The matching hash ensures that revnet deployments on different chains share identical economic parameters. It is computed inside `_makeRulesetConfigurations` by incrementally ABI-encoding the configuration fields, then taking the `keccak256` of the result.
25
+ ### Revnet Lifecycle
40
26
 
41
- Fields included in the hash (in encoding order):
42
- 1. **Base fields:** `baseCurrency`, `description.name`, `description.ticker`, `description.salt`
43
- 2. **Per-stage fields** (appended for each stage): `startsAtOrAfter` (defaults to `block.timestamp` for the first stage if zero), `splitPercent`, `initialIssuance`, `issuanceCutFrequency`, `issuanceCutPercent`, `cashOutTaxRate`
44
- 3. **Per-auto-issuance fields** (appended for each auto-issuance within a stage): `chainId`, `beneficiary`, `count`
45
-
46
- The hash is stored in `hashedEncodedConfigurationOf[revnetId]` and used as part of the CREATE2 salt when deploying suckers via `SUCKER_REGISTRY.deploySuckersFor`. This guarantees that cross-chain sucker peers can only be deployed for revnets whose economic configuration matches exactly — a deployment on Chain B with different stage parameters would produce a different hash, a different salt, and therefore a different sucker address, preventing it from peering with Chain A's suckers.
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
- Note that `splits` (the specific split recipient addresses) are **not** included in the hash. Splits may contain chain-specific addresses, so they are excluded to allow legitimate cross-chain deployments where the only difference is the split recipient addresses.
38
+ ### Loan Lifecycle
49
39
 
50
- #### Auto-Issuance
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
- Auto-issuance pre-allocates tokens to specified beneficiaries when a stage begins. Each `REVAutoIssuance` entry specifies a `chainId`, a `beneficiary` address, and a token `count`.
48
+ ## Critical Invariants
53
49
 
54
- During deployment, the deployer records auto-issuance amounts in `amountToAutoIssue[revnetId][stageId][beneficiary]` but only for entries whose `chainId` matches `block.chainid`. Entries for other chains are still included in the matching hash (ensuring cross-chain consistency) but are skipped for on-chain storage.
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
- Claiming is a separate step: anyone can call `autoIssueFor(revnetId, stageId, beneficiary)` after the stage has started. This function verifies the stage's ruleset has begun (`ruleset.start <= block.timestamp`), zeroes the stored amount, and calls `CONTROLLER.mintTokensOf` to mint tokens directly to the beneficiary — bypassing the reserved percent so the full count goes to the beneficiary.
55
+ ## Where Complexity Lives
57
56
 
58
- Stage IDs are assigned as `block.timestamp + i` (where `i` is the stage index), matching the JBRulesets ID assignment scheme when all stages are queued in a single transaction.
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
- ### Data Hook Behavior (REVOwner)
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
- ### Loan Flow
80
- ```
81
- Borrower REVLoans.borrowFrom()
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
- ## Stage-to-Ruleset Mapping
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
- ## Dependencies
132
- - `@bananapus/core-v6` Core protocol
133
- - `@bananapus/721-hook-v6` NFT tiers
134
- - `@bananapus/buyback-hook-v6` DEX buyback
135
- - `@bananapus/suckers-v6` Cross-chain bridging
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.