@croptop/core-v6 0.0.54 → 0.0.55
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 +1 -1
- package/src/CTDeployer.sol +54 -2
package/package.json
CHANGED
package/src/CTDeployer.sol
CHANGED
|
@@ -241,6 +241,12 @@ contract CTDeployer is ERC2771Context, JBPermissioned, IJBRulesetDataHook, IERC7
|
|
|
241
241
|
if (suckerDeploymentConfiguration.salt != bytes32(0)) {
|
|
242
242
|
bytes32 suckerSalt = keccak256(abi.encode(suckerDeploymentConfiguration.salt, _msgSender()));
|
|
243
243
|
|
|
244
|
+
// A launch-time project is still owned by this deployer until the final NFT transfer, so check the
|
|
245
|
+
// intended owner before the registry sees `address(this)` as the current project owner.
|
|
246
|
+
_requireExplicitSuckerPeerPermissionFrom({
|
|
247
|
+
account: owner, projectId: projectId, suckerDeploymentConfiguration: suckerDeploymentConfiguration
|
|
248
|
+
});
|
|
249
|
+
|
|
244
250
|
// Successful deployments are discoverable from the registry, and failures are reported without reverting
|
|
245
251
|
// the project launch.
|
|
246
252
|
try SUCKER_REGISTRY.deploySuckersFor({
|
|
@@ -282,7 +288,8 @@ contract CTDeployer is ERC2771Context, JBPermissioned, IJBRulesetDataHook, IERC7
|
|
|
282
288
|
}
|
|
283
289
|
|
|
284
290
|
/// @notice Deploy new suckers for an existing project.
|
|
285
|
-
/// @dev Only the juicebox's owner can deploy new suckers.
|
|
291
|
+
/// @dev Only the juicebox's owner or a `DEPLOY_SUCKERS` operator can deploy new suckers. Supplying an explicit
|
|
292
|
+
/// non-default peer also requires `SET_SUCKER_PEER`, matching the registry's direct-call rule.
|
|
286
293
|
/// @param projectId The ID of the project to deploy suckers for.
|
|
287
294
|
/// @param suckerDeploymentConfiguration The suckers to set up for the project.
|
|
288
295
|
function deploySuckersFor(
|
|
@@ -292,11 +299,19 @@ contract CTDeployer is ERC2771Context, JBPermissioned, IJBRulesetDataHook, IERC7
|
|
|
292
299
|
external
|
|
293
300
|
returns (address[] memory suckers)
|
|
294
301
|
{
|
|
302
|
+
// Resolve the project owner once because Juicebox permissions are checked against the owner's permission table.
|
|
295
303
|
address owner = PROJECTS.ownerOf(projectId);
|
|
296
304
|
|
|
297
|
-
//
|
|
305
|
+
// `DEPLOY_SUCKERS` authorizes this wrapper to ask the registry for new suckers, but it does not authorize
|
|
306
|
+
// choosing a non-default remote peer.
|
|
298
307
|
_requirePermissionFrom({account: owner, projectId: projectId, permissionId: JBPermissionIds.DEPLOY_SUCKERS});
|
|
299
308
|
|
|
309
|
+
// Mirror the registry's explicit-peer gate against the original project authority before this wrapper becomes
|
|
310
|
+
// the registry caller.
|
|
311
|
+
_requireExplicitSuckerPeerPermissionFrom({
|
|
312
|
+
account: owner, projectId: projectId, suckerDeploymentConfiguration: suckerDeploymentConfiguration
|
|
313
|
+
});
|
|
314
|
+
|
|
300
315
|
// Deploy the suckers. The sucker registry performs its own permission check against this forwarding helper,
|
|
301
316
|
// so an unapproved CTDeployer fails at the downstream registry boundary without an extra preflight read here.
|
|
302
317
|
suckers = SUCKER_REGISTRY.deploySuckersFor({
|
|
@@ -484,4 +499,41 @@ contract CTDeployer is ERC2771Context, JBPermissioned, IJBRulesetDataHook, IERC7
|
|
|
484
499
|
function _msgSender() internal view override(ERC2771Context, Context) returns (address sender) {
|
|
485
500
|
return ERC2771Context._msgSender();
|
|
486
501
|
}
|
|
502
|
+
|
|
503
|
+
/// @notice Revert unless the caller may set explicit sucker peers for `projectId`.
|
|
504
|
+
/// @dev The registry enforces this against its direct caller. Since this deployer wraps the registry call, it must
|
|
505
|
+
/// mirror the check against the original caller so `DEPLOY_SUCKERS` alone cannot smuggle in arbitrary peers.
|
|
506
|
+
/// @param account The project owner account whose permission table is checked.
|
|
507
|
+
/// @param projectId The ID of the project to deploy suckers for.
|
|
508
|
+
/// @param suckerDeploymentConfiguration The sucker deployment configuration to inspect.
|
|
509
|
+
function _requireExplicitSuckerPeerPermissionFrom(
|
|
510
|
+
address account,
|
|
511
|
+
uint256 projectId,
|
|
512
|
+
CTSuckerDeploymentConfig calldata suckerDeploymentConfiguration
|
|
513
|
+
)
|
|
514
|
+
internal
|
|
515
|
+
view
|
|
516
|
+
{
|
|
517
|
+
// Scan every requested sucker configuration because a single explicit peer changes cross-chain authority.
|
|
518
|
+
for (uint256 i; i < suckerDeploymentConfiguration.deployerConfigurations.length;) {
|
|
519
|
+
// Cache the configured peer so the default/explicit branch is evaluated from the exact value sent onward.
|
|
520
|
+
bytes32 peer = suckerDeploymentConfiguration.deployerConfigurations[i].peer;
|
|
521
|
+
|
|
522
|
+
// `peer == 0` preserves the sucker's deterministic same-address peer behavior.
|
|
523
|
+
// Any nonzero peer is written directly into the new sucker and changes who can deliver remote roots.
|
|
524
|
+
if (peer != bytes32(0)) {
|
|
525
|
+
// Require the original project authority, not this wrapper, to authorize explicit remote peers.
|
|
526
|
+
_requirePermissionFrom({
|
|
527
|
+
account: account, projectId: projectId, permissionId: JBPermissionIds.SET_SUCKER_PEER
|
|
528
|
+
});
|
|
529
|
+
// One explicit peer is enough to prove the caller needs the stronger permission.
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
unchecked {
|
|
534
|
+
// Skip overflow checks because `i` is bounded by the calldata array length.
|
|
535
|
+
++i;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
}
|
|
487
539
|
}
|