@croptop/core-v6 0.0.15 → 0.0.17

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.
@@ -217,6 +217,9 @@ contract CTDeployer is ERC2771Context, JBPermissioned, IJBRulesetDataHook, IERC7
217
217
  //*********************************************************************//
218
218
 
219
219
  /// @notice Claim ownership of the collection.
220
+ /// @dev After calling this, the hook's owner becomes the project (resolved via PROJECTS.ownerOf). The project
221
+ /// owner must then grant CTPublisher the ADJUST_721_TIERS permission for the project so that mintFrom() continues
222
+ /// to work. Without this permission grant, all subsequent posts will revert.
220
223
  /// @param hook The hook to claim ownership of.
221
224
  function claimCollectionOwnershipOf(IJB721TiersHook hook) external override {
222
225
  // Get the project ID of the hook.
@@ -308,6 +311,9 @@ contract CTDeployer is ERC2771Context, JBPermissioned, IJBRulesetDataHook, IERC7
308
311
  }
309
312
 
310
313
  // Deploy the suckers (if applicable).
314
+ // The L2 sucker deployer fallback cascade (try primary, fall back to secondary) is
315
+ // intentionally ordered. If both deployers fail, the deployment proceeds without suckers rather than reverting,
316
+ // allowing projects to launch on unsupported chains with manual sucker setup later.
311
317
  if (suckerDeploymentConfiguration.salt != bytes32(0)) {
312
318
  // slither-disable-next-line unused-return
313
319
  SUCKER_REGISTRY.deploySuckersFor({
@@ -321,6 +327,9 @@ contract CTDeployer is ERC2771Context, JBPermissioned, IJBRulesetDataHook, IERC7
321
327
  PROJECTS.transferFrom({from: address(this), to: owner, tokenId: projectId});
322
328
 
323
329
  // Set permission for the project's owner to do all the NFT things.
330
+ // These permissions are granted from CTDeployer (address(this)), not from the project owner.
331
+ // Transferring the project NFT does not invalidate them because the permission account is CTDeployer,
332
+ // which remains the hook's owner regardless of who holds the project NFT.
324
333
  uint8[] memory permissionIds = new uint8[](4);
325
334
  permissionIds[0] = JBPermissionIds.ADJUST_721_TIERS;
326
335
  permissionIds[1] = JBPermissionIds.SET_721_METADATA;
@@ -11,6 +11,9 @@ import {ICTProjectOwner} from "./interfaces/ICTProjectOwner.sol";
11
11
  import {ICTPublisher} from "./interfaces/ICTPublisher.sol";
12
12
 
13
13
  /// @notice A contract that can be sent a project to be burned, while still allowing croptop posts.
14
+ /// @dev This contract does not expose any function to reconfigure posting criteria. This is by design: posting
15
+ /// criteria are set before transferring the project here, and become immutable once ownership is transferred.
16
+ /// The project owner should configure all desired posting criteria before sending the project NFT to this contract.
14
17
  contract CTProjectOwner is IERC721Receiver, ICTProjectOwner {
15
18
  //*********************************************************************//
16
19
  // ---------------- public immutable stored properties --------------- //
@@ -71,7 +74,7 @@ contract CTProjectOwner is IERC721Receiver, ICTProjectOwner {
71
74
  permissionsData: JBPermissionsData({
72
75
  operator: address(PUBLISHER),
73
76
  // forge-lint: disable-next-line(unsafe-typecast)
74
- projectId: uint56(tokenId),
77
+ projectId: uint64(tokenId),
75
78
  permissionIds: permissionIds
76
79
  })
77
80
  });
@@ -1,8 +1,6 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  pragma solidity 0.8.26;
3
3
 
4
- import {ERC2771Context} from "@openzeppelin/contracts/metatx/ERC2771Context.sol";
5
- import {Context} from "@openzeppelin/contracts/utils/Context.sol";
6
4
  import {IJB721TiersHook} from "@bananapus/721-hook-v6/src/interfaces/IJB721TiersHook.sol";
7
5
  import {IJB721TiersHookStore} from "@bananapus/721-hook-v6/src/interfaces/IJB721TiersHookStore.sol";
8
6
  import {JB721Tier} from "@bananapus/721-hook-v6/src/structs/JB721Tier.sol";
@@ -15,6 +13,8 @@ import {JBConstants} from "@bananapus/core-v6/src/libraries/JBConstants.sol";
15
13
  import {JBMetadataResolver} from "@bananapus/core-v6/src/libraries/JBMetadataResolver.sol";
16
14
  import {JBOwnable} from "@bananapus/ownable-v6/src/JBOwnable.sol";
17
15
  import {JBPermissionIds} from "@bananapus/permission-ids-v6/src/JBPermissionIds.sol";
16
+ import {ERC2771Context} from "@openzeppelin/contracts/metatx/ERC2771Context.sol";
17
+ import {Context} from "@openzeppelin/contracts/utils/Context.sol";
18
18
 
19
19
  import {ICTPublisher} from "./interfaces/ICTPublisher.sol";
20
20
  import {CTAllowedPost} from "./structs/CTAllowedPost.sol";
@@ -108,6 +108,9 @@ contract CTPublisher is JBPermissioned, ERC2771Context, ICTPublisher {
108
108
  //*********************************************************************//
109
109
 
110
110
  /// @notice Get the tiers for the provided encoded IPFS URIs.
111
+ /// @dev The returned tier IDs may be stale if the corresponding tiers were removed externally via adjustTiers.
112
+ /// In that case, the store's tierOf call will return a tier with default/empty values. Callers should check
113
+ /// the returned tier's initialSupply or other fields to confirm the tier still exists.
111
114
  /// @param hook The hook from which to get tiers.
112
115
  /// @param encodedIPFSUris The URIs to get tiers of.
113
116
  /// @return tiers The tiers that correspond to the provided encoded IPFS URIs. If there's no tier yet, an empty tier
@@ -234,6 +237,9 @@ contract CTPublisher is JBPermissioned, ERC2771Context, ICTPublisher {
234
237
 
235
238
  /// @notice Collection owners can set the allowed criteria for publishing a new NFT to their project.
236
239
  /// @param allowedPosts An array of criteria for allowed posts.
240
+ // Categories cannot be fully disabled after creation. This is by design — once a category is
241
+ // created, removing posting would break expectations for existing posters. Projects can set restrictive
242
+ // allowedPost configurations to effectively disable new posts without removing the category.
237
243
  function configurePostingCriteriaFor(CTAllowedPost[] memory allowedPosts) external override {
238
244
  // Keep a reference to the number of post criteria.
239
245
  uint256 numberOfAllowedPosts = allowedPosts.length;
@@ -332,7 +338,14 @@ contract CTPublisher is JBPermissioned, ERC2771Context, ICTPublisher {
332
338
  // Note: integer division truncates, so the fee loses up to (FEE_DIVISOR - 1) wei of dust.
333
339
  // For example, a totalPrice of 39 wei with FEE_DIVISOR=20 yields a fee of 1 wei instead of 1.95.
334
340
  // This rounding is in the payer's favor and the loss is negligible for practical amounts.
335
- payValue -= totalPrice / FEE_DIVISOR;
341
+ uint256 fee = totalPrice / FEE_DIVISOR;
342
+
343
+ // Make sure enough ETH was sent to cover the fee.
344
+ if (payValue < fee) {
345
+ revert CTPublisher_InsufficientEthSent(totalPrice + fee, msg.value);
346
+ }
347
+
348
+ payValue -= fee;
336
349
  }
337
350
 
338
351
  // Make sure the amount sent to this function is at least the specified price of the tier plus the fee.
@@ -394,6 +407,9 @@ contract CTPublisher is JBPermissioned, ERC2771Context, ICTPublisher {
394
407
  }
395
408
 
396
409
  // Pay a fee if there are funds left.
410
+ // Force-sent ETH (via selfdestruct or coinbase) cannot be prevented. Routing it to the fee
411
+ // project (project #1) is the safest option — it prevents ETH from being permanently locked and benefits the
412
+ // protocol.
397
413
  if (address(this).balance != 0) {
398
414
  // Get a reference to the fee project's current ETH payment terminal.
399
415
  IJBTerminal feeTerminal =
@@ -24,6 +24,8 @@ interface ICTDeployer {
24
24
  function PUBLISHER() external view returns (ICTPublisher);
25
25
 
26
26
  /// @notice Claim ownership of a tiered ERC-721 hook collection by transferring it to the project.
27
+ /// @dev After claiming, the project owner must grant CTPublisher the ADJUST_721_TIERS permission for the project
28
+ /// so that mintFrom() continues to work.
27
29
  /// @param hook The hook to claim ownership of. The caller must own the project the hook belongs to.
28
30
  function claimCollectionOwnershipOf(IJB721TiersHook hook) external;
29
31