@bananapus/omnichain-deployers-v6 0.0.48 → 0.0.50

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bananapus/omnichain-deployers-v6",
3
- "version": "0.0.48",
3
+ "version": "0.0.50",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -25,7 +25,7 @@
25
25
  },
26
26
  "dependencies": {
27
27
  "@bananapus/721-hook-v6": "^0.0.55",
28
- "@bananapus/core-v6": "^0.0.60",
28
+ "@bananapus/core-v6": "^0.0.64",
29
29
  "@bananapus/ownable-v6": "^0.0.28",
30
30
  "@bananapus/permission-ids-v6": "^0.0.27",
31
31
  "@bananapus/suckers-v6": "^0.0.52",
@@ -155,10 +155,10 @@ contract JBOmnichainDeployer is
155
155
 
156
156
  /// @notice Deploy new cross-chain suckers for an existing project. Each sucker enables token bridging between this
157
157
  /// chain and a peer chain. The registry also maps configured tokens on each new sucker in the same call.
158
- /// @dev Only the project's owner or an operator with `JBPermissionIds.DEPLOY_SUCKERS` can call this. The salt
159
- /// includes `msg.sender` for replay protection the same sender must call on both chains for deterministic
160
- /// address
161
- /// matching.
158
+ /// @dev Only the project's owner or an operator with `JBPermissionIds.DEPLOY_SUCKERS` can call this. Supplying
159
+ /// an explicit non-default peer also requires `JBPermissionIds.SET_SUCKER_PEER`, matching the registry's
160
+ /// direct-call authorization model. The salt includes `msg.sender` for replay protection — the same sender must
161
+ /// call on both chains for deterministic address matching.
162
162
  /// @param projectId The ID of the project to deploy suckers for.
163
163
  /// @param suckerDeploymentConfiguration The suckers to set up for the project.
164
164
  function deploySuckersFor(
@@ -169,9 +169,17 @@ contract JBOmnichainDeployer is
169
169
  override
170
170
  returns (address[] memory suckers)
171
171
  {
172
- // Enforce permissions.
173
- _requirePermissionFrom({
174
- account: PROJECTS.ownerOf(projectId), projectId: projectId, permissionId: JBPermissionIds.DEPLOY_SUCKERS
172
+ // Resolve the project owner once because Juicebox permissions are checked against the owner's permission table.
173
+ address owner = PROJECTS.ownerOf(projectId);
174
+
175
+ // `DEPLOY_SUCKERS` authorizes this wrapper to ask the registry for new suckers, but it does not authorize
176
+ // choosing a non-default remote peer.
177
+ _requirePermissionFrom({account: owner, projectId: projectId, permissionId: JBPermissionIds.DEPLOY_SUCKERS});
178
+
179
+ // Mirror the registry's explicit-peer gate against the original project authority before this wrapper becomes
180
+ // the registry caller.
181
+ _requireExplicitSuckerPeerPermissionFrom({
182
+ account: owner, projectId: projectId, suckerDeploymentConfiguration: suckerDeploymentConfiguration
175
183
  });
176
184
 
177
185
  // Deploy the suckers.
@@ -207,6 +215,7 @@ contract JBOmnichainDeployer is
207
215
  JBSuckerDeploymentConfig calldata suckerDeploymentConfiguration
208
216
  )
209
217
  external
218
+ payable
210
219
  override
211
220
  returns (uint256 projectId, IJB721TiersHook hook, address[] memory suckers)
212
221
  {
@@ -241,6 +250,7 @@ contract JBOmnichainDeployer is
241
250
  JBSuckerDeploymentConfig calldata suckerDeploymentConfiguration
242
251
  )
243
252
  external
253
+ payable
244
254
  override
245
255
  returns (uint256 projectId, IJB721TiersHook hook, address[] memory suckers)
246
256
  {
@@ -771,7 +781,7 @@ contract JBOmnichainDeployer is
771
781
  returns (uint256 projectId, IJB721TiersHook hook, address[] memory suckers)
772
782
  {
773
783
  // Reserve the project ID up front so permissionless project creations cannot invalidate hook deployment.
774
- projectId = PROJECTS.createFor(address(this));
784
+ projectId = PROJECTS.createFor{value: msg.value}(address(this));
775
785
 
776
786
  // A fresh project can start without a controller, but it must not already be assigned elsewhere.
777
787
  _requireController({projectId: projectId, allowUnset: true});
@@ -802,6 +812,12 @@ contract JBOmnichainDeployer is
802
812
 
803
813
  // Deploy the suckers (if applicable).
804
814
  if (suckerDeploymentConfiguration.salt != bytes32(0)) {
815
+ // A launch-time project is still owned by this wrapper until the final NFT transfer, so check the
816
+ // intended owner before the registry sees `address(this)` as the current project owner.
817
+ _requireExplicitSuckerPeerPermissionFrom({
818
+ account: owner, projectId: projectId, suckerDeploymentConfiguration: suckerDeploymentConfiguration
819
+ });
820
+
805
821
  suckers = SUCKER_REGISTRY.deploySuckersFor({
806
822
  projectId: projectId,
807
823
  salt: keccak256(abi.encode(suckerDeploymentConfiguration.salt, _msgSender())),
@@ -1056,4 +1072,42 @@ contract JBOmnichainDeployer is
1056
1072
  });
1057
1073
  }
1058
1074
  }
1075
+
1076
+ /// @notice Revert unless the caller may set explicit sucker peers for `projectId`.
1077
+ /// @dev The registry enforces this against its direct caller. Since this deployer wraps the registry call, it must
1078
+ /// mirror the check against the original caller so `DEPLOY_SUCKERS` alone cannot smuggle in arbitrary peers.
1079
+ /// @param account The project owner account whose permission table is checked.
1080
+ /// @param projectId The ID of the project to deploy suckers for.
1081
+ /// @param suckerDeploymentConfiguration The sucker deployment configuration to inspect.
1082
+ function _requireExplicitSuckerPeerPermissionFrom(
1083
+ address account,
1084
+ uint256 projectId,
1085
+ JBSuckerDeploymentConfig calldata suckerDeploymentConfiguration
1086
+ )
1087
+ internal
1088
+ view
1089
+ {
1090
+ // Scan every requested sucker configuration because a single explicit peer changes cross-chain authority.
1091
+ for (uint256 i; i < suckerDeploymentConfiguration.deployerConfigurations.length;) {
1092
+ // Cache the configured peer so the default/explicit branch is evaluated from the exact value sent onward.
1093
+ bytes32 peer = suckerDeploymentConfiguration.deployerConfigurations[i].peer;
1094
+
1095
+ // `peer == 0` preserves the sucker's deterministic same-address peer behavior.
1096
+ // Any nonzero peer is written directly into the new sucker and changes who can deliver remote roots.
1097
+ if (peer != bytes32(0)) {
1098
+ // Require the original project authority, not this wrapper, to authorize explicit remote peers.
1099
+ _requirePermissionFrom({
1100
+ account: account, projectId: projectId, permissionId: JBPermissionIds.SET_SUCKER_PEER
1101
+ });
1102
+
1103
+ // One explicit peer is enough to prove the caller needs the stronger permission.
1104
+ return;
1105
+ }
1106
+
1107
+ unchecked {
1108
+ // Skip overflow checks because `i` is bounded by the calldata array length.
1109
+ ++i;
1110
+ }
1111
+ }
1112
+ }
1059
1113
  }
@@ -77,6 +77,7 @@ interface IJBOmnichainDeployer {
77
77
  JBSuckerDeploymentConfig calldata suckerDeploymentConfiguration
78
78
  )
79
79
  external
80
+ payable
80
81
  returns (uint256 projectId, IJB721TiersHook hook, address[] memory suckers);
81
82
 
82
83
  /// @notice Creates a project with a default (empty-tier) 721 hook and with suckers.
@@ -98,6 +99,7 @@ interface IJBOmnichainDeployer {
98
99
  JBSuckerDeploymentConfig calldata suckerDeploymentConfiguration
99
100
  )
100
101
  external
102
+ payable
101
103
  returns (uint256 projectId, IJB721TiersHook hook, address[] memory suckers);
102
104
 
103
105
  /// @notice Launches new rulesets for a project with a 721 tiers hook attached.