@rev-net/core-v6 0.0.10 → 0.0.12

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.
Files changed (49) hide show
  1. package/ADMINISTRATION.md +7 -7
  2. package/ARCHITECTURE.md +11 -11
  3. package/README.md +7 -4
  4. package/RISKS.md +2 -2
  5. package/SKILLS.md +8 -10
  6. package/STYLE_GUIDE.md +14 -1
  7. package/package.json +9 -9
  8. package/script/Deploy.s.sol +85 -35
  9. package/script/helpers/RevnetCoreDeploymentLib.sol +12 -5
  10. package/src/REVDeployer.sol +121 -129
  11. package/src/REVLoans.sol +14 -13
  12. package/src/interfaces/IREVDeployer.sol +25 -22
  13. package/src/structs/REVDeploy721TiersHookConfig.sol +12 -14
  14. package/test/REV.integrations.t.sol +17 -8
  15. package/test/REVAutoIssuanceFuzz.t.sol +9 -4
  16. package/test/REVDeployerRegressions.t.sol +13 -6
  17. package/test/REVInvincibility.t.sol +26 -12
  18. package/test/REVLifecycle.t.sol +9 -4
  19. package/test/REVLoans.invariants.t.sol +13 -6
  20. package/test/REVLoansAttacks.t.sol +12 -5
  21. package/test/REVLoansFeeRecovery.t.sol +12 -5
  22. package/test/REVLoansFindings.t.sol +16 -7
  23. package/test/REVLoansRegressions.t.sol +9 -4
  24. package/test/REVLoansSourced.t.sol +24 -11
  25. package/test/REVLoansUnSourced.t.sol +13 -6
  26. package/test/TestBurnHeldTokens.t.sol +16 -7
  27. package/test/TestCEIPattern.t.sol +12 -5
  28. package/test/TestCashOutCallerValidation.t.sol +12 -5
  29. package/test/TestConversionDocumentation.t.sol +25 -9
  30. package/test/TestCrossSourceReallocation.t.sol +12 -5
  31. package/test/TestEmptyBuybackSpecs.t.sol +23 -8
  32. package/test/TestFlashLoanSurplus.t.sol +12 -5
  33. package/test/TestHookArrayOOB.t.sol +19 -10
  34. package/test/TestLiquidationBehavior.t.sol +12 -5
  35. package/test/TestLowFindings.t.sol +16 -7
  36. package/test/TestMixedFixes.t.sol +16 -7
  37. package/test/TestSplitWeightAdjustment.t.sol +29 -12
  38. package/test/TestSplitWeightE2E.t.sol +24 -16
  39. package/test/TestSplitWeightFork.t.sol +20 -14
  40. package/test/TestStageTransitionBorrowable.t.sol +15 -5
  41. package/test/TestSwapTerminalPermission.t.sol +15 -5
  42. package/test/TestUint112Overflow.t.sol +12 -5
  43. package/test/TestZeroRepayment.t.sol +12 -5
  44. package/test/fork/ForkTestBase.sol +20 -14
  45. package/test/fork/TestCashOutFork.t.sol +8 -2
  46. package/test/fork/TestLoanCrossRulesetFork.t.sol +8 -2
  47. package/test/helpers/REVEmpty721Config.sol +45 -0
  48. package/test/regression/TestCumulativeLoanCounter.t.sol +12 -5
  49. package/test/regression/TestLiquidateGapHandling.t.sol +12 -5
package/ADMINISTRATION.md CHANGED
@@ -35,8 +35,7 @@ Admin privileges and their scope in revnet-core-v6. Revnets are designed to be a
35
35
 
36
36
  | Function | Required Role | Permission ID | What It Does |
37
37
  |----------|--------------|---------------|-------------|
38
- | `deployFor()` | Anyone (new revnet) or Juicebox project owner (existing project) | None | Deploys a new revnet or irreversibly converts an existing Juicebox project into a revnet. |
39
- | `deployWith721sFor()` | Anyone (new revnet) or Juicebox project owner (existing project) | None | Same as `deployFor()` but also deploys a tiered ERC-721 hook and optional croptop posting rules. |
38
+ | `deployFor()` | Anyone (new revnet) or Juicebox project owner (existing project) | None | Deploys a new revnet or irreversibly converts an existing Juicebox project into a revnet. Both variants deploy a tiered ERC-721 hook: the 4-arg variant deploys a default empty hook; the 6-arg variant deploys a hook with pre-configured tiers and optional croptop posting rules. |
40
39
  | `deploySuckersFor()` | Split Operator | Checked via `_checkIfIsSplitOperatorOf()` | Deploys new cross-chain suckers for an existing revnet. Also requires the current ruleset's `extraMetadata` bit 2 to be set (allows deploying suckers). |
41
40
  | `setSplitOperatorOf()` | Split Operator | Checked via `_checkIfIsSplitOperatorOf()` | Replaces the current split operator with a new address. Revokes all operator permissions from the caller and grants them to the new address. |
42
41
  | `autoIssueFor()` | Anyone | None | Mints pre-configured auto-issuance tokens for a beneficiary once the relevant stage has started. Amounts are set at deployment and can only be claimed once. |
@@ -57,15 +56,16 @@ The split operator receives the following Juicebox permission IDs, scoped to its
57
56
  | `SUCKER_SAFETY` | Manage sucker safety settings (e.g., emergency hatch). |
58
57
  | `SET_BUYBACK_HOOK` | Configure the buyback hook. |
59
58
  | `SET_ROUTER_TERMINAL` | Set the router terminal. |
59
+ | `SET_TOKEN_METADATA` | Update the revnet token's name and symbol. |
60
60
 
61
61
  Optional 721 permissions (granted only if enabled at deployment via `REVDeploy721TiersHookConfig`):
62
62
 
63
63
  | Permission ID | Deployment Flag | What It Allows |
64
64
  |---------------|----------------|----------------|
65
- | `ADJUST_721_TIERS` | `splitOperatorCanAdjustTiers` | Add or remove ERC-721 tiers. |
66
- | `SET_721_METADATA` | `splitOperatorCanUpdateMetadata` | Update ERC-721 tier metadata. |
67
- | `MINT_721` | `splitOperatorCanMint` | Mint ERC-721s without payment from tiers with `allowOwnerMint`. |
68
- | `SET_721_DISCOUNT_PERCENT` | `splitOperatorCanIncreaseDiscountPercent` | Increase the discount percentage of a tier. |
65
+ | `ADJUST_721_TIERS` | `preventSplitOperatorAdjustingTiers` | Add or remove ERC-721 tiers. Allowed unless prevented. |
66
+ | `SET_721_METADATA` | `preventSplitOperatorUpdatingMetadata` | Update ERC-721 tier metadata. Allowed unless prevented. |
67
+ | `MINT_721` | `preventSplitOperatorMinting` | Mint ERC-721s without payment from tiers with `allowOwnerMint`. Allowed unless prevented. |
68
+ | `SET_721_DISCOUNT_PERCENT` | `preventSplitOperatorIncreasingDiscountPercent` | Increase the discount percentage of a tier. Allowed unless prevented. |
69
69
 
70
70
  ### REVLoans
71
71
 
@@ -112,7 +112,7 @@ The `REVLoans` contract has minimal admin surface by design:
112
112
 
113
113
  The following parameters are set at deployment and can never be changed:
114
114
 
115
- ### REVDeployer (per-revnet, set at `deployFor` / `deployWith721sFor` time)
115
+ ### REVDeployer (per-revnet, set at `deployFor` time)
116
116
  - Stage schedule (start times, issuance rates, cut frequencies, cut percentages)
117
117
  - Cash-out tax rates per stage
118
118
  - Split percentages per stage
package/ARCHITECTURE.md CHANGED
@@ -9,7 +9,7 @@ Autonomous revenue networks ("revnets") built on Juicebox V6. REVDeployer create
9
9
  ```
10
10
  src/
11
11
  ├── REVDeployer.sol — Deploys revnets: stages → rulesets, data hook, buyback, suckers, 721 tiers
12
- ├── REVLoans.sol — Borrow against locked revnet tokens (10-year max, gradual liquidation)
12
+ ├── REVLoans.sol — Borrow against burned revnet tokens (10-year max, permissionless liquidation)
13
13
  ├── interfaces/
14
14
  │ ├── IREVDeployer.sol
15
15
  │ └── IREVLoans.sol
@@ -28,7 +28,7 @@ Deployer → REVDeployer.deployFor()
28
28
  → Set REVDeployer as data hook (controls pay + cashout behavior)
29
29
  → Initialize buyback pools at 1:1 price, configure buyback hook
30
30
  → Deploy suckers for cross-chain operation
31
- → Deploy 721 tiers if specified
31
+ → Deploy tiered ERC-721 hook (always — empty by default, pre-configured if specified)
32
32
  → Compute matching hash for cross-chain deployment verification
33
33
  ```
34
34
 
@@ -47,18 +47,18 @@ Cash Out → REVDeployer.beforeCashOutRecordedWith()
47
47
  ### Loan Flow
48
48
  ```
49
49
  Borrower → REVLoans.borrowFrom()
50
- Lock borrower's revnet tokens as collateral
50
+ Burn borrower's revnet tokens as collateral
51
51
  → Calculate max borrow based on bonding curve value
52
- Transfer borrowed funds to borrower
53
- Create loan with 10-year max term
52
+ Pull funds from treasury via USE_ALLOWANCE
53
+ Mint loan ERC-721 NFT to borrower
54
54
 
55
55
  Repay → REVLoans.repayLoan()
56
- → Accept repayment (principal + prepay fee)
57
- Return locked collateral tokens to borrower
56
+ → Accept repayment (principal + prepaid fee)
57
+ Re-mint collateral tokens to borrower
58
58
 
59
- Liquidate → REVLoans.liquidateLoan()
60
- → After loan term, gradually release collateral
61
- Liquidation schedule spreads over time
59
+ Liquidate → REVLoans.liquidateExpiredLoansFrom()
60
+ → After 10-year term, anyone can liquidate
61
+ Collateral permanently destroyed (was burned at borrow time)
62
62
  ```
63
63
 
64
64
  ## Extension Points
@@ -84,4 +84,4 @@ Liquidate → REVLoans.liquidateLoan()
84
84
  - Stages are immutable after deployment — no owner can change ruleset parameters
85
85
  - Matching hash ensures cross-chain deployments have identical economic parameters
86
86
  - REVDeployer is the data hook for all revnets it deploys — centralizes behavioral control
87
- - Loans use bonding curve value, not market price — immune to external price manipulation
87
+ - Loans use bonding curve value, not market price — independent of external DEX pricing
package/README.md CHANGED
@@ -54,8 +54,10 @@ Revnets are autonomous Juicebox projects with predetermined economic stages. Eac
54
54
 
55
55
  ### Deployer Variants
56
56
 
57
- - **Basic revnet** -- `deployFor` with stage configurations mapped to Juicebox rulesets.
58
- - **Tiered 721 revnet** -- `deployWith721sFor` adds a tiered 721 pay hook that mints NFTs as people pay.
57
+ Every revnet gets a tiered ERC-721 hook deployed automatically even if no tiers are configured at launch. This lets the split operator add and sell NFTs later without migration.
58
+
59
+ - **Basic revnet** -- `deployFor` with stage configurations mapped to Juicebox rulesets and an empty 721 hook.
60
+ - **Tiered 721 revnet** -- `deployFor` adds a tiered 721 pay hook with pre-configured tiers that mint NFTs as people pay.
59
61
  - **Croptop revnet** -- A tiered 721 revnet with Croptop posting criteria, allowing the public to post content.
60
62
 
61
63
  ## Architecture
@@ -102,8 +104,8 @@ If `forge install` has issues, try `git submodule update --init --recursive`.
102
104
 
103
105
  ```
104
106
  src/
105
- REVDeployer.sol # Revnet deployer + data hook (~1,256 lines)
106
- REVLoans.sol # Token-collateralized lending (~1,333 lines)
107
+ REVDeployer.sol # Revnet deployer + data hook (~1,287 lines)
108
+ REVLoans.sol # Token-collateralized lending (~1,359 lines)
107
109
  interfaces/
108
110
  IREVDeployer.sol # Deployer interface + events
109
111
  IREVLoans.sol # Loans interface + events
@@ -159,6 +161,7 @@ The split operator has these default permissions:
159
161
  | `SUCKER_SAFETY` | Emergency sucker functions |
160
162
  | `SET_BUYBACK_HOOK` | Swap buyback hook |
161
163
  | `SET_ROUTER_TERMINAL` | Swap terminal |
164
+ | `SET_TOKEN_METADATA` | Update token name and symbol |
162
165
 
163
166
  Plus optional from 721 hook config: `ADJUST_721_TIERS`, `SET_721_METADATA`, `MINT_721`, `SET_721_DISCOUNT_PERCENT`.
164
167
 
package/RISKS.md CHANGED
@@ -44,6 +44,6 @@ When a revnet expands to a chain where the native token is not ETH (e.g., Celo),
44
44
 
45
45
  | Function | Protection | Risk |
46
46
  |----------|-----------|------|
47
- | `REVLoans.borrowFrom` | Collateral locked BEFORE funds transferred | LOW |
48
- | `REVLoans.repayLoan` | Loan state cleared BEFORE collateral returned | LOW |
47
+ | `REVLoans.borrowFrom` | Collateral burned BEFORE funds transferred | LOW |
48
+ | `REVLoans.repayLoan` | Loan state cleared BEFORE collateral re-minted | LOW |
49
49
  | `REVDeployer.beforePayRecordedWith` | View function, no state changes | NONE |
package/SKILLS.md CHANGED
@@ -8,8 +8,8 @@ Deploy and manage Revnets -- autonomous, unowned Juicebox projects with staged i
8
8
 
9
9
  | Contract | Role |
10
10
  |----------|------|
11
- | `REVDeployer` | Deploys revnets, permanently owns the project NFT, acts as data hook and cash-out hook. Manages stages, splits, auto-issuance, buyback hooks, 721 hooks, suckers, and split operators. (~1,256 lines) |
12
- | `REVLoans` | Issues token-collateralized loans from revnet treasuries. Each loan is an ERC-721 NFT. Burns collateral on borrow, re-mints on repay. Charges tiered fees (REV protocol fee + source fee + prepaid fee). (~1,333 lines) |
11
+ | `REVDeployer` | Deploys revnets, permanently owns the project NFT, acts as data hook and cash-out hook. Manages stages, splits, auto-issuance, buyback hooks, 721 hooks, suckers, and split operators. (~1,287 lines) |
12
+ | `REVLoans` | Issues token-collateralized loans from revnet treasuries. Each loan is an ERC-721 NFT. Burns collateral on borrow, re-mints on repay. Charges tiered fees (REV protocol fee + source fee + prepaid fee). (~1,359 lines) |
13
13
 
14
14
  ## Key Functions
15
15
 
@@ -17,8 +17,8 @@ Deploy and manage Revnets -- autonomous, unowned Juicebox projects with staged i
17
17
 
18
18
  | Function | What it does |
19
19
  |----------|-------------|
20
- | `REVDeployer.deployFor(revnetId, config, terminals, suckerConfig)` | Deploy a new revnet (`revnetId=0`) or convert an existing Juicebox project. Encodes stage configs into rulesets, deploys ERC-20 token, initializes buyback pool at 1:1 price, sets up split operator, suckers, and loans permissions. |
21
- | `REVDeployer.deployWith721sFor(revnetId, config, terminals, suckerConfig, hookConfig, allowedPosts)` | Same as `deployFor` but also deploys a tiered ERC-721 hook. Optionally configures Croptop posting criteria and grants publisher permission to add tiers. |
20
+ | `REVDeployer.deployFor(revnetId, config, terminals, suckerConfig)` | Deploy a new revnet (`revnetId=0`) or convert an existing Juicebox project. Encodes stage configs into rulesets, deploys ERC-20 token, initializes buyback pool at 1:1 price, sets up split operator, suckers, loans permissions, and deploys a default empty tiered ERC-721 hook. |
21
+ | `REVDeployer.deployFor(revnetId, config, terminals, suckerConfig, hookConfig, allowedPosts)` | Same as `deployFor` but deploys a tiered ERC-721 hook with pre-configured tiers. Optionally configures Croptop posting criteria and grants publisher permission to add tiers. |
22
22
  | `REVDeployer.deploySuckersFor(revnetId, suckerConfig)` | Deploy new cross-chain suckers post-launch. Split operator only. Validates ruleset allows sucker deployment (bit 2 of `extraMetadata`). Uses stored config hash for cross-chain matching. |
23
23
 
24
24
  ### Data Hooks
@@ -80,13 +80,13 @@ Deploy and manage Revnets -- autonomous, unowned Juicebox projects with staged i
80
80
 
81
81
  | Struct | Key Fields | Used In |
82
82
  |--------|------------|---------|
83
- | `REVConfig` | `description` (REVDescription), `baseCurrency`, `splitOperator`, `stageConfigurations[]`, `loanSources[]`, `loans` | `deployFor`, `deployWith721sFor` |
83
+ | `REVConfig` | `description` (REVDescription), `baseCurrency`, `splitOperator`, `stageConfigurations[]` | `deployFor` |
84
84
  | `REVStageConfig` | `startsAtOrAfter` (uint48), `initialIssuance` (uint112), `issuanceCutFrequency` (uint32), `issuanceCutPercent` (uint32), `cashOutTaxRate` (uint16), `splitPercent` (uint16), `splits[]`, `autoIssuances[]`, `extraMetadata` (uint16) | Translated into `JBRulesetConfig` |
85
85
  | `REVDescription` | `name`, `ticker`, `uri`, `salt` | ERC-20 token deployment and project metadata |
86
86
  | `REVAutoIssuance` | `chainId` (uint32), `count` (uint104), `beneficiary` | Per-stage cross-chain token auto-minting |
87
87
  | `REVLoan` | `amount` (uint112), `collateral` (uint112), `createdAt` (uint48), `prepaidFeePercent` (uint16), `prepaidDuration` (uint32), `source` (REVLoanSource) | Per-loan state in `REVLoans` |
88
88
  | `REVLoanSource` | `token`, `terminal` (IJBPayoutTerminal) | Identifies which terminal and token a loan draws from |
89
- | `REVDeploy721TiersHookConfig` | `baseline721HookConfiguration` (REVBaseline721HookConfig), `salt`, `splitOperatorCanAdjustTiers`, `CanUpdateMetadata`, `CanMint`, `CanIncreaseDiscountPercent` | 721 hook deployment with operator permissions. Uses `REVBaseline721HookConfig` (not `JBDeploy721TiersHookConfig`) to omit `issueTokensForSplits` — revnets always force it to `false`. |
89
+ | `REVDeploy721TiersHookConfig` | `baseline721HookConfiguration` (REVBaseline721HookConfig), `salt`, `preventSplitOperatorAdjustingTiers`, `preventSplitOperatorUpdatingMetadata`, `preventSplitOperatorMinting`, `preventSplitOperatorIncreasingDiscountPercent` | 721 hook deployment with operator permissions (preventive flags — `false` = allowed). Uses `REVBaseline721HookConfig` (not `JBDeploy721TiersHookConfig`) to omit `issueTokensForSplits` — revnets always force it to `false`. |
90
90
  | `REVBaseline721HookConfig` | `name`, `symbol`, `baseUri`, `tokenUriResolver`, `contractUri`, `tiersConfig`, `reserveBeneficiary`, `flags` (REV721TiersHookFlags) | Same as `JBDeploy721TiersHookConfig` but uses `REV721TiersHookFlags` which omits `issueTokensForSplits`. |
91
91
  | `REV721TiersHookFlags` | `noNewTiersWithReserves`, `noNewTiersWithVotes`, `noNewTiersWithOwnerMinting`, `preventOverspending` | Same as `JB721TiersHookFlags` minus `issueTokensForSplits`. Revnets do their own weight adjustment for splits. |
92
92
  | `REVCroptopAllowedPost` | `category` (uint24), `minimumPrice` (uint104), `minimumTotalSupply` (uint32), `maximumTotalSupply` (uint32), `allowedAddresses[]` | Croptop posting criteria |
@@ -212,11 +212,9 @@ REVConfig memory config = REVConfig({
212
212
  uri: "ipfs://...",
213
213
  salt: bytes32(0)
214
214
  }),
215
- baseCurrency: 1, // USD
215
+ baseCurrency: 1, // ETH
216
216
  splitOperator: msg.sender,
217
- stageConfigurations: stages,
218
- loanSources: new REVLoanSource[](0),
219
- loans: address(0) // No loans contract
217
+ stageConfigurations: stages
220
218
  });
221
219
 
222
220
  deployer.deployFor({
package/STYLE_GUIDE.md CHANGED
@@ -253,9 +253,12 @@ uint256 public constant MAX_RESERVED_PERCENT = 10_000;
253
253
 
254
254
  ## Function Calls
255
255
 
256
- Use named parameters for readability when calling functions with 3+ arguments:
256
+ Use named arguments for all function calls with 2 or more arguments — in both `src/` and `script/`:
257
257
 
258
258
  ```solidity
259
+ // Good — named arguments
260
+ token.mint({account: beneficiary, amount: count});
261
+ _transferOwnership({newOwner: address(0), projectId: 0});
259
262
  PERMISSIONS.hasPermission({
260
263
  operator: sender,
261
264
  account: account,
@@ -264,8 +267,18 @@ PERMISSIONS.hasPermission({
264
267
  includeRoot: true,
265
268
  includeWildcardProjectId: true
266
269
  });
270
+
271
+ // Bad — positional arguments with 2+ args
272
+ token.mint(beneficiary, count);
273
+ _transferOwnership(address(0), 0);
267
274
  ```
268
275
 
276
+ Single-argument calls use positional style: `_burn(amount)`.
277
+
278
+ This also applies to constructor calls, struct literals, and inherited/library calls (e.g., OZ `_mint`, `_safeMint`, `safeTransfer`, `allowance`, `Clones.cloneDeterministic`).
279
+
280
+ Named argument keys must use **camelCase** — never underscores. If a function's parameter names use underscores, rename them to camelCase first.
281
+
269
282
  ## Multiline Signatures
270
283
 
271
284
  ```solidity
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rev-net/core-v6",
3
- "version": "0.0.10",
3
+ "version": "0.0.12",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -20,14 +20,14 @@
20
20
  "artifacts": "source ./.env && npx sphinx artifacts --org-id 'ea165b21-7cdc-4d7b-be59-ecdd4c26bee4' --project-name 'revnet-core-v6'"
21
21
  },
22
22
  "dependencies": {
23
- "@bananapus/721-hook-v6": "^0.0.14",
24
- "@bananapus/buyback-hook-v6": "^0.0.11",
25
- "@bananapus/core-v6": "^0.0.15",
26
- "@bananapus/ownable-v6": "^0.0.8",
27
- "@bananapus/permission-ids-v6": "^0.0.7",
28
- "@bananapus/router-terminal-v6": "^0.0.10",
29
- "@bananapus/suckers-v6": "^0.0.9",
30
- "@croptop/core-v6": "^0.0.14",
23
+ "@bananapus/721-hook-v6": "^0.0.16",
24
+ "@bananapus/buyback-hook-v6": "^0.0.12",
25
+ "@bananapus/core-v6": "^0.0.16",
26
+ "@bananapus/ownable-v6": "^0.0.9",
27
+ "@bananapus/permission-ids-v6": "^0.0.9",
28
+ "@bananapus/router-terminal-v6": "^0.0.11",
29
+ "@bananapus/suckers-v6": "^0.0.10",
30
+ "@croptop/core-v6": "^0.0.15",
31
31
  "@openzeppelin/contracts": "^5.6.1",
32
32
  "@uniswap/v4-core": "^1.0.2",
33
33
  "@uniswap/v4-periphery": "^1.0.3"
@@ -31,11 +31,21 @@ import {REVDescription} from "../src/structs/REVDescription.sol";
31
31
  import {REVStageConfig} from "../src/structs/REVStageConfig.sol";
32
32
  import {REVSuckerDeploymentConfig} from "../src/structs/REVSuckerDeploymentConfig.sol";
33
33
  import {REVLoans, IREVLoans} from "./../src/REVLoans.sol";
34
+ import {REVDeploy721TiersHookConfig} from "../src/structs/REVDeploy721TiersHookConfig.sol";
35
+ import {REVCroptopAllowedPost} from "../src/structs/REVCroptopAllowedPost.sol";
36
+ import {IJB721TokenUriResolver} from "@bananapus/721-hook-v6/src/interfaces/IJB721TokenUriResolver.sol";
37
+ import {IJBPrices} from "@bananapus/core-v6/src/interfaces/IJBPrices.sol";
38
+ import {JB721InitTiersConfig} from "@bananapus/721-hook-v6/src/structs/JB721InitTiersConfig.sol";
39
+ import {JB721TierConfig} from "@bananapus/721-hook-v6/src/structs/JB721TierConfig.sol";
40
+ import {REVBaseline721HookConfig} from "../src/structs/REVBaseline721HookConfig.sol";
41
+ import {REV721TiersHookFlags} from "../src/structs/REV721TiersHookFlags.sol";
34
42
 
35
43
  struct FeeProjectConfig {
36
44
  REVConfig configuration;
37
45
  JBTerminalConfig[] terminalConfigurations;
38
46
  REVSuckerDeploymentConfig suckerDeploymentConfiguration;
47
+ REVDeploy721TiersHookConfig tiered721HookConfiguration;
48
+ REVCroptopAllowedPost[] allowedPosts;
39
49
  }
40
50
 
41
51
  contract DeployScript is Script, Sphinx {
@@ -90,32 +100,43 @@ contract DeployScript is Script, Sphinx {
90
100
  // Get the deployment addresses for the nana CORE for this chain.
91
101
  // We want to do this outside of the `sphinx` modifier.
92
102
  core = CoreDeploymentLib.getDeployment(
93
- vm.envOr("NANA_CORE_DEPLOYMENT_PATH", string("node_modules/@bananapus/core-v6/deployments/"))
103
+ vm.envOr({
104
+ name: "NANA_CORE_DEPLOYMENT_PATH", defaultValue: string("node_modules/@bananapus/core-v6/deployments/")
105
+ })
94
106
  );
95
107
  // Get the deployment addresses for the suckers contracts for this chain.
96
108
  suckers = SuckerDeploymentLib.getDeployment(
97
- vm.envOr("NANA_SUCKERS_DEPLOYMENT_PATH", string("node_modules/@bananapus/suckers-v6/deployments/"))
109
+ vm.envOr({
110
+ name: "NANA_SUCKERS_DEPLOYMENT_PATH",
111
+ defaultValue: string("node_modules/@bananapus/suckers-v6/deployments/")
112
+ })
98
113
  );
99
114
  // Get the deployment addresses for the 721 hook contracts for this chain.
100
115
  croptop = CroptopDeploymentLib.getDeployment(
101
- vm.envOr("CROPTOP_CORE_DEPLOYMENT_PATH", string("node_modules/@croptop/core-v6/deployments/"))
116
+ vm.envOr({
117
+ name: "CROPTOP_CORE_DEPLOYMENT_PATH", defaultValue: string("node_modules/@croptop/core-v6/deployments/")
118
+ })
102
119
  );
103
120
  // Get the deployment addresses for the 721 hook contracts for this chain.
104
121
  hook = Hook721DeploymentLib.getDeployment(
105
- vm.envOr("NANA_721_DEPLOYMENT_PATH", string("node_modules/@bananapus/721-hook-v6/deployments/"))
122
+ vm.envOr({
123
+ name: "NANA_721_DEPLOYMENT_PATH",
124
+ defaultValue: string("node_modules/@bananapus/721-hook-v6/deployments/")
125
+ })
106
126
  );
107
127
  // Get the deployment addresses for the router terminal contracts for this chain.
108
128
  routerTerminal = RouterTerminalDeploymentLib.getDeployment(
109
- vm.envOr(
110
- "NANA_ROUTER_TERMINAL_DEPLOYMENT_PATH",
111
- string("node_modules/@bananapus/router-terminal-v6/deployments/")
112
- )
129
+ vm.envOr({
130
+ name: "NANA_ROUTER_TERMINAL_DEPLOYMENT_PATH",
131
+ defaultValue: string("node_modules/@bananapus/router-terminal-v6/deployments/")
132
+ })
113
133
  );
114
134
  // Get the deployment addresses for the 721 hook contracts for this chain.
115
135
  buybackHook = BuybackDeploymentLib.getDeployment(
116
- vm.envOr(
117
- "NANA_BUYBACK_HOOK_DEPLOYMENT_PATH", string("node_modules/@bananapus/buyback-hook-v6/deployments/")
118
- )
136
+ vm.envOr({
137
+ name: "NANA_BUYBACK_HOOK_DEPLOYMENT_PATH",
138
+ defaultValue: string("node_modules/@bananapus/buyback-hook-v6/deployments/")
139
+ })
119
140
  );
120
141
 
121
142
  // We use the same trusted forwarder and permit2 as the core deployment.
@@ -210,7 +231,7 @@ contract DeployScript is Script, Sphinx {
210
231
 
211
232
  // The project's revnet configuration
212
233
  REVConfig memory revnetConfiguration = REVConfig({
213
- description: REVDescription(NAME, SYMBOL, PROJECT_URI, ERC20_SALT),
234
+ description: REVDescription({name: NAME, ticker: SYMBOL, uri: PROJECT_URI, salt: ERC20_SALT}),
214
235
  baseCurrency: ETH_CURRENCY,
215
236
  splitOperator: OPERATOR,
216
237
  stageConfigurations: stageConfigurations
@@ -262,7 +283,32 @@ contract DeployScript is Script, Sphinx {
262
283
  return FeeProjectConfig({
263
284
  configuration: revnetConfiguration,
264
285
  terminalConfigurations: terminalConfigurations,
265
- suckerDeploymentConfiguration: suckerDeploymentConfiguration
286
+ suckerDeploymentConfiguration: suckerDeploymentConfiguration,
287
+ tiered721HookConfiguration: REVDeploy721TiersHookConfig({
288
+ baseline721HookConfiguration: REVBaseline721HookConfig({
289
+ name: "",
290
+ symbol: "",
291
+ baseUri: "",
292
+ tokenUriResolver: IJB721TokenUriResolver(address(0)),
293
+ contractUri: "",
294
+ tiersConfig: JB721InitTiersConfig({
295
+ tiers: new JB721TierConfig[](0), currency: ETH_CURRENCY, decimals: 18
296
+ }),
297
+ reserveBeneficiary: address(0),
298
+ flags: REV721TiersHookFlags({
299
+ noNewTiersWithReserves: false,
300
+ noNewTiersWithVotes: false,
301
+ noNewTiersWithOwnerMinting: false,
302
+ preventOverspending: false
303
+ })
304
+ }),
305
+ salt: bytes32(0),
306
+ preventSplitOperatorAdjustingTiers: false,
307
+ preventSplitOperatorUpdatingMetadata: false,
308
+ preventSplitOperatorMinting: false,
309
+ preventSplitOperatorIncreasingDiscountPercent: false
310
+ }),
311
+ allowedPosts: new REVCroptopAllowedPost[](0)
266
312
  });
267
313
  }
268
314
 
@@ -271,11 +317,13 @@ contract DeployScript is Script, Sphinx {
271
317
  uint256 FEE_PROJECT_ID = core.projects.createFor(safeAddress());
272
318
 
273
319
  // Deploy REVLoans first — it only depends on the controller.
274
- (address _revloansAddr, bool _revloansIsDeployed) = _isDeployed(
275
- REVLOANS_SALT,
276
- type(REVLoans).creationCode,
277
- abi.encode(core.controller, core.projects, FEE_PROJECT_ID, LOANS_OWNER, PERMIT2, TRUSTED_FORWARDER)
278
- );
320
+ (address _revloansAddr, bool _revloansIsDeployed) = _isDeployed({
321
+ salt: REVLOANS_SALT,
322
+ creationCode: type(REVLoans).creationCode,
323
+ arguments: abi.encode(
324
+ core.controller, core.projects, FEE_PROJECT_ID, LOANS_OWNER, PERMIT2, TRUSTED_FORWARDER
325
+ )
326
+ });
279
327
  REVLoans revloans = _revloansIsDeployed
280
328
  ? REVLoans(payable(_revloansAddr))
281
329
  : new REVLoans{salt: REVLOANS_SALT}({
@@ -288,10 +336,10 @@ contract DeployScript is Script, Sphinx {
288
336
  });
289
337
 
290
338
  // Deploy REVDeployer with the REVLoans and buyback hook addresses.
291
- (address _deployerAddr, bool _deployerIsDeployed) = _isDeployed(
292
- DEPLOYER_SALT,
293
- type(REVDeployer).creationCode,
294
- abi.encode(
339
+ (address _deployerAddr, bool _deployerIsDeployed) = _isDeployed({
340
+ salt: DEPLOYER_SALT,
341
+ creationCode: type(REVDeployer).creationCode,
342
+ arguments: abi.encode(
295
343
  core.controller,
296
344
  suckers.registry,
297
345
  FEE_PROJECT_ID,
@@ -301,22 +349,22 @@ contract DeployScript is Script, Sphinx {
301
349
  address(revloans),
302
350
  TRUSTED_FORWARDER
303
351
  )
304
- );
352
+ });
305
353
  REVDeployer _basicDeployer = _deployerIsDeployed
306
354
  ? REVDeployer(payable(_deployerAddr))
307
- : new REVDeployer{salt: DEPLOYER_SALT}(
308
- core.controller,
309
- suckers.registry,
310
- FEE_PROJECT_ID,
311
- hook.hook_deployer,
312
- croptop.publisher,
313
- IJBBuybackHookRegistry(address(buybackHook.registry)),
314
- address(revloans),
315
- TRUSTED_FORWARDER
316
- );
355
+ : new REVDeployer{salt: DEPLOYER_SALT}({
356
+ controller: core.controller,
357
+ suckerRegistry: suckers.registry,
358
+ feeRevnetId: FEE_PROJECT_ID,
359
+ hookDeployer: hook.hook_deployer,
360
+ publisher: croptop.publisher,
361
+ buybackHook: IJBBuybackHookRegistry(address(buybackHook.registry)),
362
+ loans: address(revloans),
363
+ trustedForwarder: TRUSTED_FORWARDER
364
+ });
317
365
 
318
366
  // Approve the basic deployer to configure the project.
319
- core.projects.approve(address(_basicDeployer), FEE_PROJECT_ID);
367
+ core.projects.approve({to: address(_basicDeployer), tokenId: FEE_PROJECT_ID});
320
368
 
321
369
  // Build the config.
322
370
  FeeProjectConfig memory feeProjectConfig = getFeeProjectConfig();
@@ -326,7 +374,9 @@ contract DeployScript is Script, Sphinx {
326
374
  revnetId: FEE_PROJECT_ID,
327
375
  configuration: feeProjectConfig.configuration,
328
376
  terminalConfigurations: feeProjectConfig.terminalConfigurations,
329
- suckerDeploymentConfiguration: feeProjectConfig.suckerDeploymentConfiguration
377
+ suckerDeploymentConfiguration: feeProjectConfig.suckerDeploymentConfiguration,
378
+ tiered721HookConfiguration: feeProjectConfig.tiered721HookConfiguration,
379
+ allowedPosts: feeProjectConfig.allowedPosts
330
380
  });
331
381
  }
332
382
 
@@ -29,7 +29,7 @@ library RevnetCoreDeploymentLib {
29
29
 
30
30
  for (uint256 _i; _i < networks.length; _i++) {
31
31
  if (networks[_i].chainId == chainId) {
32
- return getDeployment(path, networks[_i].name);
32
+ return getDeployment({path: path, network_name: networks[_i].name});
33
33
  }
34
34
  }
35
35
 
@@ -44,10 +44,17 @@ library RevnetCoreDeploymentLib {
44
44
  view
45
45
  returns (RevnetCoreDeployment memory deployment)
46
46
  {
47
- deployment.basic_deployer =
48
- IREVDeployer(_getDeploymentAddress(path, "revnet-core-v6", network_name, "REVDeployer"));
47
+ deployment.basic_deployer = IREVDeployer(
48
+ _getDeploymentAddress({
49
+ path: path, project_name: "revnet-core-v6", network_name: network_name, contractName: "REVDeployer"
50
+ })
51
+ );
49
52
 
50
- deployment.loans = IREVLoans(_getDeploymentAddress(path, "revnet-core-v6", network_name, "REVLoans"));
53
+ deployment.loans = IREVLoans(
54
+ _getDeploymentAddress({
55
+ path: path, project_name: "revnet-core-v6", network_name: network_name, contractName: "REVLoans"
56
+ })
57
+ );
51
58
  }
52
59
 
53
60
  /// @notice Get the address of a contract that was deployed by the Deploy script.
@@ -67,6 +74,6 @@ library RevnetCoreDeploymentLib {
67
74
  {
68
75
  string memory deploymentJson =
69
76
  vm.readFile(string.concat(path, project_name, "/", network_name, "/", contractName, ".json"));
70
- return stdJson.readAddress(deploymentJson, ".address");
77
+ return stdJson.readAddress({json: deploymentJson, key: ".address"});
71
78
  }
72
79
  }