@bananapus/suckers-v6 0.0.39 → 0.0.40

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/suckers-v6",
3
- "version": "0.0.39",
3
+ "version": "0.0.40",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -31,7 +31,7 @@
31
31
  "dependencies": {
32
32
  "@arbitrum/nitro-contracts": "3.2.0",
33
33
  "@bananapus/core-v6": "^0.0.44",
34
- "@bananapus/permission-ids-v6": "^0.0.23",
34
+ "@bananapus/permission-ids-v6": "^0.0.25",
35
35
  "@chainlink/contracts-ccip": "1.6.4",
36
36
  "@chainlink/local": "0.2.7",
37
37
  "@openzeppelin/contracts": "5.6.1",
@@ -497,6 +497,13 @@ contract JBSuckerRegistry is ERC2771Context, Ownable, JBPermissioned, IJBSuckerR
497
497
  // default peer symmetry assumption will not hold.
498
498
  salt = keccak256(abi.encode(sender, salt));
499
499
 
500
+ // Cache the project owner so the explicit-peer gate can check against the original authority, not a
501
+ // delegated operator. The default same-address peering invariant (peer == 0 or peer == address(this))
502
+ // does not need this stronger gate, but a non-symmetric explicit peer authorizes that arbitrary address
503
+ // to deliver outbox roots and mint project tokens — so it must require a permission strictly broader
504
+ // than ops automation's `DEPLOY_SUCKERS`.
505
+ address projectOwner = PROJECTS.ownerOf(projectId);
506
+
500
507
  // Iterate through the configurations and deploy the suckers.
501
508
  for (uint256 i; i < configurations.length;) {
502
509
  // Get the configuration being iterated over.
@@ -507,6 +514,18 @@ contract JBSuckerRegistry is ERC2771Context, Ownable, JBPermissioned, IJBSuckerR
507
514
  revert JBSuckerRegistry_InvalidDeployer({deployer: configuration.deployer});
508
515
  }
509
516
 
517
+ // If the configuration specifies a non-symmetric explicit peer, require the additional
518
+ // `SET_SUCKER_PEER` permission. Default peering (peer == 0 or peer == bytes32 of address(this)) is
519
+ // unaffected. Without this gate, a delegated operator with only `DEPLOY_SUCKERS` could register an
520
+ // attacker peer and use the resulting sucker's mint authority to deliver fabricated outbox roots.
521
+ // forge-lint: disable-next-line(unsafe-typecast)
522
+ bytes32 selfPeer = bytes32(uint256(uint160(address(this))));
523
+ if (configuration.peer != bytes32(0) && configuration.peer != selfPeer) {
524
+ _requirePermissionFrom({
525
+ account: projectOwner, projectId: projectId, permissionId: JBPermissionIds.SET_SUCKER_PEER
526
+ });
527
+ }
528
+
510
529
  // Create the sucker.
511
530
  IJBSucker sucker = configuration.deployer
512
531
  .createForSender({localProjectId: projectId, salt: salt, peer: configuration.peer});