@bananapus/omnichain-deployers-v6 0.0.31 → 0.0.34
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/CHANGELOG.md +1 -1
- package/README.md +2 -2
- package/foundry.toml +2 -1
- package/package.json +20 -11
- package/src/JBOmnichainDeployer.sol +34 -20
- package/src/interfaces/IJBOmnichainDeployer.sol +4 -0
- package/ADMINISTRATION.md +0 -29
- package/ARCHITECTURE.md +0 -31
- package/AUDIT_INSTRUCTIONS.md +0 -29
- package/RISKS.md +0 -97
- package/SKILLS.md +0 -25
- package/STYLE_GUIDE.md +0 -610
- package/USER_JOURNEYS.md +0 -63
- package/foundry.lock +0 -11
- package/slither-ci.config.json +0 -10
- package/sphinx.lock +0 -491
- package/test/JBOmnichainDeployer.t.sol +0 -639
- package/test/JBOmnichainDeployerGuard.t.sol +0 -404
- package/test/OmnichainDeployerAttacks.t.sol +0 -432
- package/test/OmnichainDeployerEdgeCases.t.sol +0 -827
- package/test/OmnichainDeployerReentrancy.t.sol +0 -321
- package/test/TestAuditGaps.sol +0 -996
- package/test/Tiered721HookComposition.t.sol +0 -909
- package/test/audit/AuditFixesC2H6M14.t.sol +0 -480
- package/test/audit/CarryForwardRejectedHook.t.sol +0 -328
- package/test/audit/CashOutCountPropagation.t.sol +0 -232
- package/test/audit/CashOutSpecMerge.t.sol +0 -372
- package/test/audit/DeterministicDrift.t.sol +0 -78
- package/test/audit/DeterministicPeerDrift.t.sol +0 -79
- package/test/audit/ExtraCashOutHookZeroReclaim.t.sol +0 -340
- package/test/audit/ForwardedPermissions.t.sol +0 -297
- package/test/audit/JBOmnichainDeployer.t.sol +0 -321
- package/test/audit/NftCashoutSupplyMismatch.t.sol +0 -224
- package/test/audit/OmnichainAudit.t.sol +0 -168
- package/test/audit/SplitCreditWeight.t.sol +0 -437
- package/test/audit/WeightScalingComparison.t.sol +0 -350
- package/test/fork/OmnichainForkTestBase.sol +0 -535
- package/test/fork/TestOmnichain721QueueAndAdjust.t.sol +0 -252
- package/test/fork/TestOmnichainCashOutFork.t.sol +0 -184
- package/test/fork/TestOmnichainStressFork.t.sol +0 -552
- package/test/fork/TestOmnichainWeightFork.t.sol +0 -60
- package/test/fork/TestSuckerDeploymentFork.t.sol +0 -229
- package/test/invariants/CrossChainDeployerInvariant.t.sol +0 -208
- package/test/invariants/OmnichainDeployerInvariant.t.sol +0 -150
- package/test/invariants/handlers/CrossChainDeployerHandler.sol +0 -394
- package/test/invariants/handlers/OmnichainDeployerHandler.sol +0 -262
- package/test/regression/EmptyRulesetConfigurations.t.sol +0 -84
- package/test/regression/HookOwnershipTransfer.t.sol +0 -152
- package/test/regression/ValidateController.t.sol +0 -169
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## v6
|
|
3
|
+
## v6 carry-forward hook fix
|
|
4
4
|
|
|
5
5
|
- **Carry-forward hook selection improved.** `queueRulesetsOf` now checks `latestQueuedOf(projectId)` before falling back to `currentOf(projectId)` when carrying forward a 721 hook. Previously it only read `currentOf`, which could miss a recently queued (and approved) ruleset's hook config. The source ruleset must have approval status `Approved` or `Empty` and a stored hook config in the deployer.
|
|
6
6
|
- The `useDataHookForCashOut` flag is preserved from whichever source ruleset is selected during carry-forward.
|
package/README.md
CHANGED
package/foundry.toml
CHANGED
|
@@ -15,7 +15,8 @@ depth = 100
|
|
|
15
15
|
fail_on_revert = false
|
|
16
16
|
|
|
17
17
|
[lint]
|
|
18
|
-
exclude_lints = ["
|
|
18
|
+
exclude_lints = ["mixed-case-variable", "pascal-case-struct"]
|
|
19
|
+
|
|
19
20
|
[fmt]
|
|
20
21
|
number_underscore = "thousands"
|
|
21
22
|
multiline_func_header = "all"
|
package/package.json
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bananapus/omnichain-deployers-v6",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.34",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/Bananapus/nana-omnichain-deployers-v6"
|
|
8
8
|
},
|
|
9
|
+
"files": [
|
|
10
|
+
"CHANGELOG.md",
|
|
11
|
+
"foundry.toml",
|
|
12
|
+
"references/",
|
|
13
|
+
"remappings.txt",
|
|
14
|
+
"script/Deploy.s.sol",
|
|
15
|
+
"script/helpers/",
|
|
16
|
+
"src/"
|
|
17
|
+
],
|
|
9
18
|
"engines": {
|
|
10
19
|
"node": ">=20.0.0"
|
|
11
20
|
},
|
|
@@ -17,17 +26,17 @@
|
|
|
17
26
|
"artifacts": "source ./.env && npx sphinx artifacts --org-id 'ea165b21-7cdc-4d7b-be59-ecdd4c26bee4' --project-name 'nana-omnichain-deployers-v6'"
|
|
18
27
|
},
|
|
19
28
|
"dependencies": {
|
|
20
|
-
"@bananapus/721-hook-v6": "
|
|
21
|
-
"@bananapus/
|
|
22
|
-
"@bananapus/
|
|
23
|
-
"@bananapus/
|
|
24
|
-
"@bananapus/
|
|
25
|
-
"@
|
|
26
|
-
"@openzeppelin/contracts": "^5.6.1",
|
|
27
|
-
"@uniswap/v4-core": "^1.0.2"
|
|
29
|
+
"@bananapus/721-hook-v6": "0.0.43",
|
|
30
|
+
"@bananapus/core-v6": "0.0.39",
|
|
31
|
+
"@bananapus/ownable-v6": "0.0.24",
|
|
32
|
+
"@bananapus/permission-ids-v6": "0.0.22",
|
|
33
|
+
"@bananapus/suckers-v6": "0.0.32",
|
|
34
|
+
"@openzeppelin/contracts": "5.6.1"
|
|
28
35
|
},
|
|
29
36
|
"devDependencies": {
|
|
30
|
-
"@bananapus/address-registry-v6": "
|
|
31
|
-
"@
|
|
37
|
+
"@bananapus/address-registry-v6": "0.0.25",
|
|
38
|
+
"@bananapus/buyback-hook-v6": "0.0.37",
|
|
39
|
+
"@sphinx-labs/plugins": "0.33.3",
|
|
40
|
+
"@uniswap/v4-core": "1.0.2"
|
|
32
41
|
}
|
|
33
42
|
}
|
|
@@ -252,6 +252,7 @@ contract JBOmnichainDeployer is
|
|
|
252
252
|
/// @notice Launches new rulesets for a project with a 721 tiers hook attached, using this contract as the data
|
|
253
253
|
/// hook.
|
|
254
254
|
/// @param projectId The ID of the project to launch the rulesets for.
|
|
255
|
+
/// @param projectUri The project's metadata URI. Pass an empty string to leave it unchanged.
|
|
255
256
|
/// @param deploy721Config The 721 hook deployment config (hook config + cash-out flag + salt).
|
|
256
257
|
/// @param rulesetConfigurations The rulesets to launch. Custom data hooks are read from each ruleset's metadata.
|
|
257
258
|
/// @param terminalConfigurations The terminals to set up for the project.
|
|
@@ -261,6 +262,7 @@ contract JBOmnichainDeployer is
|
|
|
261
262
|
/// @return hook The 721 tiers hook that was deployed for the project.
|
|
262
263
|
function launchRulesetsFor(
|
|
263
264
|
uint256 projectId,
|
|
265
|
+
string calldata projectUri,
|
|
264
266
|
JBOmnichain721Config memory deploy721Config,
|
|
265
267
|
JBRulesetConfig[] memory rulesetConfigurations,
|
|
266
268
|
JBTerminalConfig[] calldata terminalConfigurations,
|
|
@@ -273,6 +275,7 @@ contract JBOmnichainDeployer is
|
|
|
273
275
|
{
|
|
274
276
|
return _launchRulesetsFor({
|
|
275
277
|
projectId: projectId,
|
|
278
|
+
projectUri: projectUri,
|
|
276
279
|
deploy721Config: deploy721Config,
|
|
277
280
|
rulesetConfigurations: rulesetConfigurations,
|
|
278
281
|
terminalConfigurations: terminalConfigurations,
|
|
@@ -284,6 +287,7 @@ contract JBOmnichainDeployer is
|
|
|
284
287
|
/// @notice Launches new rulesets for a project with a default (empty-tier) 721 hook.
|
|
285
288
|
/// @dev Uses `baseCurrency` from the first ruleset and `decimals = 18` for the default 721 config.
|
|
286
289
|
/// @param projectId The ID of the project to launch the rulesets for.
|
|
290
|
+
/// @param projectUri The project's metadata URI. Pass an empty string to leave it unchanged.
|
|
287
291
|
/// @param rulesetConfigurations The rulesets to launch.
|
|
288
292
|
/// @param terminalConfigurations The terminals to set up for the project.
|
|
289
293
|
/// @param memo A memo to pass along to the emitted event.
|
|
@@ -292,6 +296,7 @@ contract JBOmnichainDeployer is
|
|
|
292
296
|
/// @return hook The 721 tiers hook that was deployed for the project.
|
|
293
297
|
function launchRulesetsFor(
|
|
294
298
|
uint256 projectId,
|
|
299
|
+
string calldata projectUri,
|
|
295
300
|
JBRulesetConfig[] memory rulesetConfigurations,
|
|
296
301
|
JBTerminalConfig[] calldata terminalConfigurations,
|
|
297
302
|
string calldata memo,
|
|
@@ -303,6 +308,7 @@ contract JBOmnichainDeployer is
|
|
|
303
308
|
{
|
|
304
309
|
return _launchRulesetsFor({
|
|
305
310
|
projectId: projectId,
|
|
311
|
+
projectUri: projectUri,
|
|
306
312
|
deploy721Config: _default721Config(rulesetConfigurations),
|
|
307
313
|
rulesetConfigurations: rulesetConfigurations,
|
|
308
314
|
terminalConfigurations: terminalConfigurations,
|
|
@@ -720,11 +726,12 @@ contract JBOmnichainDeployer is
|
|
|
720
726
|
internal
|
|
721
727
|
returns (uint256 projectId, IJB721TiersHook hook, address[] memory suckers)
|
|
722
728
|
{
|
|
723
|
-
//
|
|
724
|
-
projectId = PROJECTS.
|
|
729
|
+
// Reserve the project ID up front so permissionless project creations cannot invalidate hook deployment.
|
|
730
|
+
projectId = PROJECTS.createFor(address(this));
|
|
725
731
|
|
|
726
732
|
// Deploy a 721 hook and set up rulesets.
|
|
727
733
|
hook = _deploy721Hook({projectId: projectId, config: deploy721Config});
|
|
734
|
+
// slither-disable-next-line reentrancy-benign
|
|
728
735
|
rulesetConfigurations = _setup721({
|
|
729
736
|
projectId: projectId,
|
|
730
737
|
rulesetConfigurations: rulesetConfigurations,
|
|
@@ -732,18 +739,16 @@ contract JBOmnichainDeployer is
|
|
|
732
739
|
use721ForCashOut: deploy721Config.useDataHookForCashOut
|
|
733
740
|
});
|
|
734
741
|
|
|
735
|
-
// Launch the
|
|
736
|
-
// slither-disable-
|
|
737
|
-
|
|
738
|
-
projectId
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
})
|
|
746
|
-
) revert JBOmnichainDeployer_ProjectIdMismatch();
|
|
742
|
+
// Launch the rulesets for the reserved project.
|
|
743
|
+
// slither-disable-start unused-return
|
|
744
|
+
controller.launchRulesetsFor({
|
|
745
|
+
projectId: projectId,
|
|
746
|
+
projectUri: projectUri,
|
|
747
|
+
rulesetConfigurations: rulesetConfigurations,
|
|
748
|
+
terminalConfigurations: terminalConfigurations,
|
|
749
|
+
memo: memo
|
|
750
|
+
});
|
|
751
|
+
// slither-disable-end unused-return
|
|
747
752
|
|
|
748
753
|
// Transfer the hook's ownership to the project (now that the project NFT has been minted).
|
|
749
754
|
JBOwnable(address(hook)).transferOwnershipToProject(projectId);
|
|
@@ -766,6 +771,7 @@ contract JBOmnichainDeployer is
|
|
|
766
771
|
/// @notice Internal implementation of `launchRulesetsFor`.
|
|
767
772
|
function _launchRulesetsFor(
|
|
768
773
|
uint256 projectId,
|
|
774
|
+
string calldata projectUri,
|
|
769
775
|
JBOmnichain721Config memory deploy721Config,
|
|
770
776
|
JBRulesetConfig[] memory rulesetConfigurations,
|
|
771
777
|
JBTerminalConfig[] calldata terminalConfigurations,
|
|
@@ -775,15 +781,19 @@ contract JBOmnichainDeployer is
|
|
|
775
781
|
internal
|
|
776
782
|
returns (uint256 rulesetId, IJB721TiersHook hook)
|
|
777
783
|
{
|
|
784
|
+
address owner = PROJECTS.ownerOf(projectId);
|
|
785
|
+
|
|
778
786
|
// Enforce permissions. Use LAUNCH_RULESETS (not QUEUE_RULESETS) because this function calls
|
|
779
787
|
// controller.launchRulesetsFor, which sets terminals and requires the broader launch permission.
|
|
780
|
-
_requirePermissionFrom({
|
|
781
|
-
account: PROJECTS.ownerOf(projectId), projectId: projectId, permissionId: JBPermissionIds.LAUNCH_RULESETS
|
|
782
|
-
});
|
|
788
|
+
_requirePermissionFrom({account: owner, projectId: projectId, permissionId: JBPermissionIds.LAUNCH_RULESETS});
|
|
783
789
|
|
|
784
|
-
_requirePermissionFrom({
|
|
785
|
-
|
|
786
|
-
|
|
790
|
+
_requirePermissionFrom({account: owner, projectId: projectId, permissionId: JBPermissionIds.SET_TERMINALS});
|
|
791
|
+
|
|
792
|
+
if (bytes(projectUri).length != 0) {
|
|
793
|
+
_requirePermissionFrom({
|
|
794
|
+
account: owner, projectId: projectId, permissionId: JBPermissionIds.SET_PROJECT_URI
|
|
795
|
+
});
|
|
796
|
+
}
|
|
787
797
|
|
|
788
798
|
// Validate that the controller matches the project's controller in the directory.
|
|
789
799
|
_validateController({projectId: projectId, controller: controller});
|
|
@@ -802,6 +812,7 @@ contract JBOmnichainDeployer is
|
|
|
802
812
|
// Configure the rulesets.
|
|
803
813
|
rulesetId = controller.launchRulesetsFor({
|
|
804
814
|
projectId: projectId,
|
|
815
|
+
projectUri: projectUri,
|
|
805
816
|
rulesetConfigurations: rulesetConfigurations,
|
|
806
817
|
terminalConfigurations: terminalConfigurations,
|
|
807
818
|
memo: memo
|
|
@@ -830,6 +841,7 @@ contract JBOmnichainDeployer is
|
|
|
830
841
|
// Revert if the project already had rulesets queued in this block, which would make our
|
|
831
842
|
// `block.timestamp + i` ruleset ID prediction incorrect.
|
|
832
843
|
uint256 latestRulesetId = controller.RULESETS().latestRulesetIdOf(projectId);
|
|
844
|
+
// forge-lint: disable-next-line(block-timestamp)
|
|
833
845
|
if (latestRulesetId >= block.timestamp) {
|
|
834
846
|
revert JBOmnichainDeployer_RulesetIdsUnpredictable();
|
|
835
847
|
}
|
|
@@ -910,11 +922,13 @@ contract JBOmnichainDeployer is
|
|
|
910
922
|
|
|
911
923
|
// Store the 721 hook config per-ruleset.
|
|
912
924
|
// slither-disable-next-line reentrancy-benign
|
|
925
|
+
// forge-lint: disable-next-line(block-timestamp)
|
|
913
926
|
_tiered721HookOf[projectId][block.timestamp + i] =
|
|
914
927
|
JBTiered721HookConfig({hook: hook721, useDataHookForCashOut: use721ForCashOut});
|
|
915
928
|
|
|
916
929
|
// Store custom hook from metadata (same as _setup).
|
|
917
930
|
if (rulesetConfigurations[i].metadata.dataHook != address(0)) {
|
|
931
|
+
// forge-lint: disable-next-line(block-timestamp)
|
|
918
932
|
_extraDataHookOf[projectId][block.timestamp + i] = JBDeployerHookConfig({
|
|
919
933
|
dataHook: IJBRulesetDataHook(rulesetConfigurations[i].metadata.dataHook),
|
|
920
934
|
useDataHookForPay: rulesetConfigurations[i].metadata.useDataHookForPay,
|
|
@@ -100,6 +100,7 @@ interface IJBOmnichainDeployer {
|
|
|
100
100
|
|
|
101
101
|
/// @notice Launches new rulesets for a project with a 721 tiers hook attached.
|
|
102
102
|
/// @param projectId The ID of the project to launch the rulesets for.
|
|
103
|
+
/// @param projectUri The project's metadata URI. Pass an empty string to leave it unchanged.
|
|
103
104
|
/// @param deploy721Config The 721 hook deployment config (hook config + cash-out flag + salt).
|
|
104
105
|
/// @param rulesetConfigurations The rulesets to launch. Custom data hooks are read from each ruleset's metadata.
|
|
105
106
|
/// @param terminalConfigurations The terminals to set up for the project.
|
|
@@ -109,6 +110,7 @@ interface IJBOmnichainDeployer {
|
|
|
109
110
|
/// @return hook The 721 tiers hook that was deployed for the project.
|
|
110
111
|
function launchRulesetsFor(
|
|
111
112
|
uint256 projectId,
|
|
113
|
+
string calldata projectUri,
|
|
112
114
|
JBOmnichain721Config memory deploy721Config,
|
|
113
115
|
JBRulesetConfig[] memory rulesetConfigurations,
|
|
114
116
|
JBTerminalConfig[] calldata terminalConfigurations,
|
|
@@ -120,6 +122,7 @@ interface IJBOmnichainDeployer {
|
|
|
120
122
|
|
|
121
123
|
/// @notice Launches new rulesets for a project with a default (empty-tier) 721 hook.
|
|
122
124
|
/// @param projectId The ID of the project to launch the rulesets for.
|
|
125
|
+
/// @param projectUri The project's metadata URI. Pass an empty string to leave it unchanged.
|
|
123
126
|
/// @param rulesetConfigurations The rulesets to launch.
|
|
124
127
|
/// @param terminalConfigurations The terminals to set up for the project.
|
|
125
128
|
/// @param memo A memo to pass along to the emitted event.
|
|
@@ -128,6 +131,7 @@ interface IJBOmnichainDeployer {
|
|
|
128
131
|
/// @return hook The 721 tiers hook that was deployed for the project.
|
|
129
132
|
function launchRulesetsFor(
|
|
130
133
|
uint256 projectId,
|
|
134
|
+
string calldata projectUri,
|
|
131
135
|
JBRulesetConfig[] memory rulesetConfigurations,
|
|
132
136
|
JBTerminalConfig[] calldata terminalConfigurations,
|
|
133
137
|
string calldata memo,
|
package/ADMINISTRATION.md
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
# Administration
|
|
2
|
-
|
|
3
|
-
## At A Glance
|
|
4
|
-
|
|
5
|
-
| Item | Details |
|
|
6
|
-
| --- | --- |
|
|
7
|
-
| Scope | Omnichain launch orchestration and wrapper behavior |
|
|
8
|
-
| Control posture | Mixed deployer logic, project permissions, and registry trust |
|
|
9
|
-
| Highest-risk actions | Wrong hook composition, wrong sucker wiring, and bad registry trust |
|
|
10
|
-
| Recovery posture | Often requires redeploying or re-launching around bad wiring |
|
|
11
|
-
|
|
12
|
-
## Purpose
|
|
13
|
-
|
|
14
|
-
This repo controls how omnichain projects are launched and wrapped, not the low-level runtime logic of suckers or 721 hooks.
|
|
15
|
-
|
|
16
|
-
## Control Model
|
|
17
|
-
|
|
18
|
-
- launch paths are largely permissionless for new projects
|
|
19
|
-
- later ruleset changes depend on project permissions
|
|
20
|
-
- registry and sucker trust surfaces can widen authority if misconfigured
|
|
21
|
-
|
|
22
|
-
## Recovery
|
|
23
|
-
|
|
24
|
-
- bad launch wiring usually means a new deployment path rather than a local patch
|
|
25
|
-
|
|
26
|
-
## Admin Boundaries
|
|
27
|
-
|
|
28
|
-
- this repo does not override locked runtime behavior in sibling repos
|
|
29
|
-
|
package/ARCHITECTURE.md
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
# Architecture
|
|
2
|
-
|
|
3
|
-
## Purpose
|
|
4
|
-
|
|
5
|
-
`nana-omnichain-deployers-v6` packages a Juicebox project, a 721 hook, and sucker deployment into one omnichain launch surface.
|
|
6
|
-
|
|
7
|
-
## System Overview
|
|
8
|
-
|
|
9
|
-
`JBOmnichainDeployer` launches the project, stores per-ruleset hook composition, and wraps sucker behavior so bridge-triggered flows can bypass project-specific logic where intended.
|
|
10
|
-
|
|
11
|
-
## Core Invariants
|
|
12
|
-
|
|
13
|
-
- launch wiring must match the intended omnichain project shape
|
|
14
|
-
- hook composition must stay consistent with the created ruleset IDs
|
|
15
|
-
- sucker-specific privileged paths must remain limited to trusted suckers
|
|
16
|
-
- project NFT ownership and hook ownership must end in the intended place
|
|
17
|
-
|
|
18
|
-
## Trust Boundaries
|
|
19
|
-
|
|
20
|
-
- bridge runtime trust lives in `nana-suckers-v6`
|
|
21
|
-
- 721 runtime trust lives in `nana-721-hook-v6`
|
|
22
|
-
- this repo mainly owns orchestration and wrapper semantics
|
|
23
|
-
|
|
24
|
-
## Security Model
|
|
25
|
-
|
|
26
|
-
- the main risks are hook composition, ruleset ID prediction, and registry-trusted sucker bypasses
|
|
27
|
-
- this repo is not the source of underlying bridge or 721 behavior, but it can wire them together incorrectly
|
|
28
|
-
|
|
29
|
-
## Source Map
|
|
30
|
-
|
|
31
|
-
- `src/JBOmnichainDeployer.sol`
|
package/AUDIT_INSTRUCTIONS.md
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
# Audit Instructions
|
|
2
|
-
|
|
3
|
-
Audit this repo as an orchestration layer that composes 721 hooks, suckers, and optional extra data hooks.
|
|
4
|
-
|
|
5
|
-
## Audit Objective
|
|
6
|
-
|
|
7
|
-
Find issues that:
|
|
8
|
-
|
|
9
|
-
- launch the wrong project shape
|
|
10
|
-
- miscompose hooks or wrapper behavior
|
|
11
|
-
- grant privileged sucker behavior to the wrong addresses
|
|
12
|
-
- create cross-chain drift or bad deterministic assumptions
|
|
13
|
-
|
|
14
|
-
## Scope
|
|
15
|
-
|
|
16
|
-
In scope:
|
|
17
|
-
|
|
18
|
-
- `src/JBOmnichainDeployer.sol`
|
|
19
|
-
- related tests under `test/`
|
|
20
|
-
|
|
21
|
-
## Start Here
|
|
22
|
-
|
|
23
|
-
1. `src/JBOmnichainDeployer.sol`
|
|
24
|
-
|
|
25
|
-
## Verification
|
|
26
|
-
|
|
27
|
-
- `npm install`
|
|
28
|
-
- `forge build`
|
|
29
|
-
- `forge test`
|
package/RISKS.md
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
# Omnichain Deployers Risk Register
|
|
2
|
-
|
|
3
|
-
This file covers the risks in the deployer layer that launches Juicebox projects across chains while composing 721 hooks, suckers, and optional custom data hooks.
|
|
4
|
-
|
|
5
|
-
## How To Use This File
|
|
6
|
-
|
|
7
|
-
- Read `Priority risks` first. They capture the highest-blast-radius deployment and cash-out assumptions.
|
|
8
|
-
- Treat `Invariants to verify` as required checks for any new omnichain deployment flow.
|
|
9
|
-
|
|
10
|
-
## Priority Risks
|
|
11
|
-
|
|
12
|
-
| Priority | Risk | Why it matters | Primary controls |
|
|
13
|
-
|----------|------|----------------|------------------|
|
|
14
|
-
| P0 | Registry-trusted sucker bypass | This deployer gives suckers privileged cash-out behavior based on registry answers. A bad registry entry can affect many projects. | Registry allowlists, deployment verification, and explicit registry scrutiny. |
|
|
15
|
-
| P1 | Cross-chain deployment drift | Omnichain assumptions fail if chain-specific wiring, peers, or composed hooks do not match. | Deterministic deploy ordering, parity checks, and post-deploy peer verification. |
|
|
16
|
-
| P1 | Data-hook composition mistakes | The deployer wraps or forwards custom data hooks. A bad composition can alter pay or cash-out semantics unexpectedly. | Integration tests and careful forwarding review. |
|
|
17
|
-
|
|
18
|
-
## 1. Trust Assumptions
|
|
19
|
-
|
|
20
|
-
- **Trusted forwarder is trusted.**
|
|
21
|
-
- **Sucker registry answers are trusted.**
|
|
22
|
-
- **Controller trust matters.**
|
|
23
|
-
- **Extra data hooks are trusted code.**
|
|
24
|
-
|
|
25
|
-
## 2. Economic Risks
|
|
26
|
-
|
|
27
|
-
- **Sucker cashout bypass exists for registered suckers.**
|
|
28
|
-
- **Extra data hooks can manipulate weight or cash-out behavior.**
|
|
29
|
-
- **721 hook amount splitting can zero out project amount in edge cases.**
|
|
30
|
-
- **Cross-chain sender dependence affects deterministic sucker salts.**
|
|
31
|
-
|
|
32
|
-
## 3. Access Control
|
|
33
|
-
|
|
34
|
-
- **Wildcard `MAP_SUCKER_TOKEN` permission is broad.**
|
|
35
|
-
- **`launchRulesetsFor` requires combined permissions.**
|
|
36
|
-
- **`launchProjectFor` is intentionally permissionless for new projects.**
|
|
37
|
-
|
|
38
|
-
## 4. DoS Vectors
|
|
39
|
-
|
|
40
|
-
- **Ruleset ID collision can block queueing.**
|
|
41
|
-
- **External hook reverts can block pay or cash-out flows.**
|
|
42
|
-
- **721 hook deployment revert blocks launch.**
|
|
43
|
-
- **Non-safe NFT transfers can still strand assets.**
|
|
44
|
-
|
|
45
|
-
## 5. Reentrancy Surface
|
|
46
|
-
|
|
47
|
-
- **`launchProjectFor` makes several external calls in sequence.**
|
|
48
|
-
- **`beforePayRecordedWith` delegates to external hooks.**
|
|
49
|
-
- **`beforeCashOutRecordedWith` delegates to external hooks.**
|
|
50
|
-
- **There is no `ReentrancyGuard`.** The deployer relies on being effectively stateless during pay and cash-out operations.
|
|
51
|
-
|
|
52
|
-
## 6. Integration Risks
|
|
53
|
-
|
|
54
|
-
- **Hook config is keyed by predicted ruleset ID.**
|
|
55
|
-
- **Carried-forward 721 hook behavior on queue depends on prior ruleset state.**
|
|
56
|
-
- **ERC721Receiver restrictions are narrow but non-safe transfers can still strand assets.**
|
|
57
|
-
- **Empty simplified launch config reverts.**
|
|
58
|
-
|
|
59
|
-
## 7. Invariants To Verify
|
|
60
|
-
|
|
61
|
-
- launched projects point at the intended controller
|
|
62
|
-
- stored 721 hook config exists for every ruleset created through this deployer
|
|
63
|
-
- sucker cashouts always get the intended zero-tax path
|
|
64
|
-
- self-reference prevention holds after setup
|
|
65
|
-
- the project NFT ends owned by the intended owner
|
|
66
|
-
|
|
67
|
-
## 8. Accepted Behaviors
|
|
68
|
-
|
|
69
|
-
### 8.1 Controller validation is skipped during initial launch
|
|
70
|
-
|
|
71
|
-
Pre-launch controller validation is impossible because the project does not yet exist. The accepted safeguard is the post-launch project ID match check.
|
|
72
|
-
|
|
73
|
-
### 8.2 Registered suckers receive 0% cashout tax
|
|
74
|
-
|
|
75
|
-
This is intentional and shares the same trust boundary as the sucker registry.
|
|
76
|
-
|
|
77
|
-
## 9. Accepted Security Risks
|
|
78
|
-
|
|
79
|
-
Documented risks that were reviewed and accepted.
|
|
80
|
-
|
|
81
|
-
### Configuration Risks
|
|
82
|
-
|
|
83
|
-
**Unvalidated extra data hooks can brick live flows.** *(Minor)*
|
|
84
|
-
Extra data hooks provided by the project owner in `_setup721` configuration can fail and brick live pay/cashout flows. Accepted because this is self-inflicted misconfiguration — only the project owner can set these hooks.
|
|
85
|
-
|
|
86
|
-
**Missing hook721 alias check enables double invocation.** *(Minor)*
|
|
87
|
-
If the project owner configures the 721 hook as both the primary hook and as an extra data hook, it could be invoked twice. Accepted because this is self-inflicted misconfiguration — the deployer correctly processes each hook independently.
|
|
88
|
-
|
|
89
|
-
### Hook Selection
|
|
90
|
-
|
|
91
|
-
**ApprovalExpected rulesets excluded from hook carry-forward.**
|
|
92
|
-
When no new tiers are provided, the deployer carries forward the 721 hook from the most recent approved ruleset. Rulesets with `ApprovalExpected` status are intentionally excluded even though they may become active. Hook selection is irreversible — if the pending ruleset is later rejected by the approval hook, we'd have locked in a hook from a ruleset that never became active. The deployer falls back to the current (already-approved) ruleset in this case.
|
|
93
|
-
|
|
94
|
-
### Cross-Chain Deployment
|
|
95
|
-
|
|
96
|
-
**`_msgSender()` in deployment salt breaks cross-chain determinism.** *(Minor)*
|
|
97
|
-
`deploySuckersFor` includes `_msgSender()` in the CREATE2 salt, which means the same deployment from different callers produces different addresses across chains. Accepted because this is intentional replay protection — prevents frontrunning of cross-chain deployments.
|
package/SKILLS.md
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# Juicebox Omnichain Deployers
|
|
2
|
-
|
|
3
|
-
## Use This File For
|
|
4
|
-
|
|
5
|
-
- Use this file when the task involves omnichain project launch, sucker deployment, or wrapped 721-hook composition.
|
|
6
|
-
- Start here, then decide whether the issue is in launch orchestration, hook composition, or bridge-specific runtime behavior.
|
|
7
|
-
|
|
8
|
-
## Read This Next
|
|
9
|
-
|
|
10
|
-
| If you need... | Open this next |
|
|
11
|
-
|---|---|
|
|
12
|
-
| Repo overview and architecture | [`README.md`](./README.md), [`ARCHITECTURE.md`](./ARCHITECTURE.md) |
|
|
13
|
-
| Main deployer | [`src/JBOmnichainDeployer.sol`](./src/JBOmnichainDeployer.sol) |
|
|
14
|
-
| Bridge runtime | [`../nana-suckers-v6/src/JBSucker.sol`](../nana-suckers-v6/src/JBSucker.sol) |
|
|
15
|
-
| 721 hook runtime | [`../nana-721-hook-v6/src/JB721TiersHook.sol`](../nana-721-hook-v6/src/JB721TiersHook.sol) |
|
|
16
|
-
|
|
17
|
-
## Purpose
|
|
18
|
-
|
|
19
|
-
Orchestration and wrapper layer for launching projects with suckers and a 721 hook already wired in.
|
|
20
|
-
|
|
21
|
-
## Working Rules
|
|
22
|
-
|
|
23
|
-
- Start in [`src/JBOmnichainDeployer.sol`](./src/JBOmnichainDeployer.sol).
|
|
24
|
-
- Treat ruleset ID prediction as a real implementation dependency.
|
|
25
|
-
- Keep wrapper behavior and the underlying 721 or sucker behavior separate in your reasoning.
|