lens-modules 1.1.3 → 1.2.0

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.
@@ -19,7 +19,6 @@ import {LensHubEventHooks} from './base/LensHubEventHooks.sol';
19
19
 
20
20
  // Libraries
21
21
  import {ActionLib} from './libraries/ActionLib.sol';
22
- import {LegacyCollectLib} from './libraries/LegacyCollectLib.sol';
23
22
  import {FollowLib} from './libraries/FollowLib.sol';
24
23
  import {MetaTxLib} from './libraries/MetaTxLib.sol';
25
24
  import {ProfileLib} from './libraries/ProfileLib.sol';
@@ -64,12 +63,11 @@ contract LensHub is
64
63
 
65
64
  constructor(
66
65
  address followNFTImpl,
67
- address legacyCollectNFTImpl, // We still pass the deprecated CollectNFTImpl for legacy Collects to work
68
66
  address moduleRegistry,
69
67
  uint256 tokenGuardianCooldown
70
68
  )
71
69
  LensProfiles(tokenGuardianCooldown)
72
- LensImplGetters(followNFTImpl, legacyCollectNFTImpl, moduleRegistry)
70
+ LensImplGetters(followNFTImpl, moduleRegistry)
73
71
  {}
74
72
 
75
73
  /// @inheritdoc ILensProtocol
@@ -393,46 +391,6 @@ contract LensHub is
393
391
  ProfileLib.setBlockStatus(byProfileId, idsOfProfilesToSetBlockStatus, blockStatus, signature.signer);
394
392
  }
395
393
 
396
- /// @inheritdoc ILensProtocol
397
- function collectLegacy(
398
- Types.LegacyCollectParams calldata collectParams
399
- )
400
- external
401
- override
402
- whenNotPaused
403
- onlyProfileOwnerOrDelegatedExecutor(msg.sender, collectParams.collectorProfileId)
404
- returns (uint256)
405
- {
406
- return
407
- LegacyCollectLib.collect({
408
- collectParams: collectParams,
409
- transactionExecutor: msg.sender,
410
- collectorProfileOwner: ownerOf(collectParams.collectorProfileId),
411
- collectNFTImpl: this.getLegacyCollectNFTImpl()
412
- });
413
- }
414
-
415
- /// @inheritdoc ILensProtocol
416
- function collectLegacyWithSig(
417
- Types.LegacyCollectParams calldata collectParams,
418
- Types.EIP712Signature calldata signature
419
- )
420
- external
421
- override
422
- whenNotPaused
423
- onlyProfileOwnerOrDelegatedExecutor(signature.signer, collectParams.collectorProfileId)
424
- returns (uint256)
425
- {
426
- MetaTxLib.validateLegacyCollectSignature(signature, collectParams);
427
- return
428
- LegacyCollectLib.collect({
429
- collectParams: collectParams,
430
- transactionExecutor: signature.signer,
431
- collectorProfileOwner: ownerOf(collectParams.collectorProfileId),
432
- collectNFTImpl: this.getLegacyCollectNFTImpl()
433
- });
434
- }
435
-
436
394
  /// @inheritdoc ILensProtocol
437
395
  function act(
438
396
  Types.PublicationActionParams calldata publicationActionParams
@@ -560,29 +518,6 @@ contract LensHub is
560
518
  }
561
519
 
562
520
  function getFollowModule(uint256 profileId) external view returns (address) {
563
- if (__DEPRECATED__collectModuleWhitelisted[msg.sender]) {
564
- // Injecting LensHub as follow module when a Lens V1 collect module is performing the call.
565
- // This is a hack to make legacy collect work when configured for followers only.
566
- return address(this);
567
- } else {
568
- return StorageLib.getProfile(profileId).followModule;
569
- }
570
- }
571
-
572
- function isFollowing(
573
- uint256 followedProfileId,
574
- address followerAddress,
575
- uint256 /* tokenId */
576
- ) external view returns (bool) {
577
- if (__DEPRECATED__collectModuleWhitelisted[msg.sender]) {
578
- // This state was pre-filled at LegacyCollectLib and it is a hack to make legacy collect work when
579
- // configured for followers only.
580
- return
581
- _legacyCollectFollowValidationHelper[followerAddress] == followedProfileId ||
582
- ProfileLib.isExecutorApproved(followedProfileId, followerAddress) ||
583
- ProfileLib.ownerOf(followedProfileId) == followerAddress;
584
- } else {
585
- revert Errors.ExecutorInvalid();
586
- }
521
+ return StorageLib.getProfile(profileId).followModule;
587
522
  }
588
523
  }
@@ -20,23 +20,4 @@ abstract contract LensHubEventHooks is ILensHubEventHooks {
20
20
  }
21
21
  emit Events.Unfollowed(unfollowerProfileId, idOfProfileUnfollowed, transactionExecutor, block.timestamp);
22
22
  }
23
-
24
- //////////////////////////////////////
25
- /// DEPRECATED FUNCTIONS ///
26
- //////////////////////////////////////
27
-
28
- // Deprecated in V2. Kept here just for backwards compatibility with Lens V1 Collect NFTs.
29
- function emitCollectNFTTransferEvent(
30
- uint256 profileId,
31
- uint256 pubId,
32
- uint256 collectNFTId,
33
- address from,
34
- address to
35
- ) external {
36
- address expectedCollectNFT = StorageLib.getPublication(profileId, pubId).__DEPRECATED__collectNFT;
37
- if (msg.sender != expectedCollectNFT) {
38
- revert Errors.CallerNotCollectNFT();
39
- }
40
- emit Events.CollectNFTTransferred(profileId, pubId, collectNFTId, from, to, block.timestamp);
41
- }
42
23
  }
@@ -6,12 +6,10 @@ import {ILensImplGetters} from '../interfaces/ILensImplGetters.sol';
6
6
 
7
7
  contract LensImplGetters is ILensImplGetters {
8
8
  address internal immutable FOLLOW_NFT_IMPL;
9
- address internal immutable __LEGACY__COLLECT_NFT_IMPL;
10
9
  address internal immutable MODULE_REGISTRY;
11
10
 
12
- constructor(address followNFTImpl, address collectNFTImpl, address moduleRegistry) {
11
+ constructor(address followNFTImpl, address moduleRegistry) {
13
12
  FOLLOW_NFT_IMPL = followNFTImpl;
14
- __LEGACY__COLLECT_NFT_IMPL = collectNFTImpl;
15
13
  MODULE_REGISTRY = moduleRegistry;
16
14
  }
17
15
 
@@ -20,11 +18,6 @@ contract LensImplGetters is ILensImplGetters {
20
18
  return FOLLOW_NFT_IMPL;
21
19
  }
22
20
 
23
- /// @inheritdoc ILensImplGetters
24
- function getLegacyCollectNFTImpl() external view override returns (address) {
25
- return __LEGACY__COLLECT_NFT_IMPL; // LEGACY support: Used only for compatibility with V1 collectible posts.
26
- }
27
-
28
21
  /// @inheritdoc ILensImplGetters
29
22
  function getModuleRegistry() external view override returns (address) {
30
23
  return MODULE_REGISTRY;
@@ -17,14 +17,6 @@ interface ILensImplGetters {
17
17
  */
18
18
  function getFollowNFTImpl() external view returns (address);
19
19
 
20
- /**
21
- * @notice Returns the Collect NFT implementation address that is used for each new deployed Collect NFT.
22
- * @custom:pending-deprecation
23
- *
24
- * @return address The Collect NFT implementation address.
25
- */
26
- function getLegacyCollectNFTImpl() external view returns (address);
27
-
28
20
  /**
29
21
  * @notice Returns the address of the registry that stores all modules that are used by the Lens Protocol.
30
22
  *
@@ -274,28 +274,6 @@ interface ILensProtocol {
274
274
  Types.EIP712Signature calldata signature
275
275
  ) external;
276
276
 
277
- /**
278
- * @notice Collects a given publication via signature with the specified parameters.
279
- * Collect can have referrers (e.g. publications or profiles that allowed to discover the pointed publication).
280
- * @custom:permissions Collector Profile Owner or its Delegated Executor.
281
- * @custom:pending-deprecation Collect modules were replaced by PublicationAction Collect modules in V2. This method
282
- * is left here for backwards compatibility with posts made in V1 that had Collect modules.
283
- *
284
- * @param collectParams A CollectParams struct containing the parameters.
285
- *
286
- * @return uint256 An integer representing the minted token ID.
287
- */
288
- function collectLegacy(Types.LegacyCollectParams calldata collectParams) external returns (uint256);
289
-
290
- /**
291
- * @custom:meta-tx collect.
292
- * @custom:pending-deprecation
293
- */
294
- function collectLegacyWithSig(
295
- Types.LegacyCollectParams calldata collectParams,
296
- Types.EIP712Signature calldata signature
297
- ) external returns (uint256);
298
-
299
277
  /**
300
278
  * @notice Acts on a given publication with the specified parameters.
301
279
  * You can act on a publication except a mirror (if it has at least one action module initialized).
@@ -280,30 +280,6 @@ library MetaTxLib {
280
280
  );
281
281
  }
282
282
 
283
- function validateLegacyCollectSignature(
284
- Types.EIP712Signature calldata signature,
285
- Types.LegacyCollectParams calldata collectParams
286
- ) external {
287
- _validateRecoveredAddress(
288
- _calculateDigest(
289
- keccak256(
290
- abi.encode(
291
- Typehash.COLLECT_LEGACY,
292
- collectParams.publicationCollectedProfileId,
293
- collectParams.publicationCollectedId,
294
- collectParams.collectorProfileId,
295
- collectParams.referrerProfileId,
296
- collectParams.referrerPubId,
297
- _encodeUsingEip712Rules(collectParams.collectModuleData),
298
- _getNonceIncrementAndEmitEvent(signature.signer),
299
- signature.deadline
300
- )
301
- )
302
- ),
303
- signature
304
- );
305
- }
306
-
307
283
  function validateActSignature(
308
284
  Types.EIP712Signature calldata signature,
309
285
  Types.PublicationActionParams calldata publicationActionParams
@@ -7,7 +7,6 @@ import {Types} from './constants/Types.sol';
7
7
  import {Events} from './constants/Events.sol';
8
8
  import {Errors} from './constants/Errors.sol';
9
9
  import {IReferenceModule} from '../interfaces/IReferenceModule.sol';
10
- import {ILegacyReferenceModule} from '../interfaces/ILegacyReferenceModule.sol';
11
10
  import {StorageLib} from './StorageLib.sol';
12
11
  import {IPublicationActionModule} from '../interfaces/IPublicationActionModule.sol';
13
12
  import {IModuleRegistry} from '../interfaces/IModuleRegistry.sol';
@@ -344,42 +343,19 @@ library PublicationLib {
344
343
  .getPublication(commentParams.pointedProfileId, commentParams.pointedPubId)
345
344
  .referenceModule;
346
345
  if (refModule != address(0)) {
347
- try
348
- IReferenceModule(refModule).processComment(
349
- Types.ProcessCommentParams({
350
- profileId: commentParams.profileId,
351
- pubId: pubIdAssigned,
352
- transactionExecutor: transactionExecutor,
353
- pointedProfileId: commentParams.pointedProfileId,
354
- pointedPubId: commentParams.pointedPubId,
355
- referrerProfileIds: commentParams.referrerProfileIds,
356
- referrerPubIds: commentParams.referrerPubIds,
357
- referrerPubTypes: referrerPubTypes,
358
- data: commentParams.referenceModuleData
359
- })
360
- )
361
- returns (bytes memory returnData) {
362
- return (returnData);
363
- } catch (bytes memory err) {
364
- assembly {
365
- /// Equivalent to reverting with the returned error selector if
366
- /// the length is not zero.
367
- let length := mload(err)
368
- if iszero(iszero(length)) {
369
- revert(add(err, 32), length)
370
- }
371
- }
372
- if (commentParams.referrerProfileIds.length > 0) {
373
- // Deprecated reference modules don't support referrers.
374
- revert Errors.InvalidReferrer();
375
- }
376
- ILegacyReferenceModule(refModule).processComment(
377
- commentParams.profileId,
378
- commentParams.pointedProfileId,
379
- commentParams.pointedPubId,
380
- commentParams.referenceModuleData
381
- );
382
- }
346
+ IReferenceModule(refModule).processComment(
347
+ Types.ProcessCommentParams({
348
+ profileId: commentParams.profileId,
349
+ pubId: pubIdAssigned,
350
+ transactionExecutor: transactionExecutor,
351
+ pointedProfileId: commentParams.pointedProfileId,
352
+ pointedPubId: commentParams.pointedPubId,
353
+ referrerProfileIds: commentParams.referrerProfileIds,
354
+ referrerPubIds: commentParams.referrerPubIds,
355
+ referrerPubTypes: referrerPubTypes,
356
+ data: commentParams.referenceModuleData
357
+ })
358
+ );
383
359
  } else {
384
360
  if (commentParams.referrerProfileIds.length > 0) {
385
361
  // We don't allow referrers if the reference module is not set.
@@ -399,42 +375,19 @@ library PublicationLib {
399
375
  .getPublication(quoteParams.pointedProfileId, quoteParams.pointedPubId)
400
376
  .referenceModule;
401
377
  if (refModule != address(0)) {
402
- try
403
- IReferenceModule(refModule).processQuote(
404
- Types.ProcessQuoteParams({
405
- profileId: quoteParams.profileId,
406
- pubId: pubIdAssigned,
407
- transactionExecutor: transactionExecutor,
408
- pointedProfileId: quoteParams.pointedProfileId,
409
- pointedPubId: quoteParams.pointedPubId,
410
- referrerProfileIds: quoteParams.referrerProfileIds,
411
- referrerPubIds: quoteParams.referrerPubIds,
412
- referrerPubTypes: referrerPubTypes,
413
- data: quoteParams.referenceModuleData
414
- })
415
- )
416
- returns (bytes memory returnData) {
417
- return (returnData);
418
- } catch (bytes memory err) {
419
- assembly {
420
- /// Equivalent to reverting with the returned error selector if
421
- /// the length is not zero.
422
- let length := mload(err)
423
- if iszero(iszero(length)) {
424
- revert(add(err, 32), length)
425
- }
426
- }
427
- if (quoteParams.referrerProfileIds.length > 0) {
428
- // Deprecated reference modules don't support referrers.
429
- revert Errors.InvalidReferrer();
430
- }
431
- ILegacyReferenceModule(refModule).processComment(
432
- quoteParams.profileId,
433
- quoteParams.pointedProfileId,
434
- quoteParams.pointedPubId,
435
- quoteParams.referenceModuleData
436
- );
437
- }
378
+ IReferenceModule(refModule).processQuote(
379
+ Types.ProcessQuoteParams({
380
+ profileId: quoteParams.profileId,
381
+ pubId: pubIdAssigned,
382
+ transactionExecutor: transactionExecutor,
383
+ pointedProfileId: quoteParams.pointedProfileId,
384
+ pointedPubId: quoteParams.pointedPubId,
385
+ referrerProfileIds: quoteParams.referrerProfileIds,
386
+ referrerPubIds: quoteParams.referrerPubIds,
387
+ referrerPubTypes: referrerPubTypes,
388
+ data: quoteParams.referenceModuleData
389
+ })
390
+ );
438
391
  } else {
439
392
  if (quoteParams.referrerProfileIds.length > 0) {
440
393
  // We don't allow referrers if the reference module is not set.
@@ -454,42 +407,19 @@ library PublicationLib {
454
407
  .getPublication(mirrorParams.pointedProfileId, mirrorParams.pointedPubId)
455
408
  .referenceModule;
456
409
  if (refModule != address(0)) {
457
- try
458
- IReferenceModule(refModule).processMirror(
459
- Types.ProcessMirrorParams({
460
- profileId: mirrorParams.profileId,
461
- pubId: pubIdAssigned,
462
- transactionExecutor: transactionExecutor,
463
- pointedProfileId: mirrorParams.pointedProfileId,
464
- pointedPubId: mirrorParams.pointedPubId,
465
- referrerProfileIds: mirrorParams.referrerProfileIds,
466
- referrerPubIds: mirrorParams.referrerPubIds,
467
- referrerPubTypes: referrerPubTypes,
468
- data: mirrorParams.referenceModuleData
469
- })
470
- )
471
- returns (bytes memory returnData) {
472
- return (returnData);
473
- } catch (bytes memory err) {
474
- assembly {
475
- /// Equivalent to reverting with the returned error selector if
476
- /// the length is not zero.
477
- let length := mload(err)
478
- if iszero(iszero(length)) {
479
- revert(add(err, 32), length)
480
- }
481
- }
482
- if (mirrorParams.referrerProfileIds.length > 0) {
483
- // Deprecated reference modules don't support referrers.
484
- revert Errors.InvalidReferrer();
485
- }
486
- ILegacyReferenceModule(refModule).processMirror(
487
- mirrorParams.profileId,
488
- mirrorParams.pointedProfileId,
489
- mirrorParams.pointedPubId,
490
- mirrorParams.referenceModuleData
491
- );
492
- }
410
+ IReferenceModule(refModule).processMirror(
411
+ Types.ProcessMirrorParams({
412
+ profileId: mirrorParams.profileId,
413
+ pubId: pubIdAssigned,
414
+ transactionExecutor: transactionExecutor,
415
+ pointedProfileId: mirrorParams.pointedProfileId,
416
+ pointedPubId: mirrorParams.pointedPubId,
417
+ referrerProfileIds: mirrorParams.referrerProfileIds,
418
+ referrerPubIds: mirrorParams.referrerPubIds,
419
+ referrerPubTypes: referrerPubTypes,
420
+ data: mirrorParams.referenceModuleData
421
+ })
422
+ );
493
423
  } else {
494
424
  if (mirrorParams.referrerProfileIds.length > 0) {
495
425
  // We don't allow referrers if the reference module is not set.
@@ -115,28 +115,6 @@ library ValidationLib {
115
115
  return referrerPubTypes;
116
116
  }
117
117
 
118
- function validateLegacyCollectReferrer(
119
- uint256 referrerProfileId,
120
- uint256 referrerPubId,
121
- uint256 publicationCollectedProfileId,
122
- uint256 publicationCollectedId
123
- ) external view {
124
- if (
125
- !ProfileLib.exists(referrerProfileId) ||
126
- PublicationLib.getPublicationType(referrerProfileId, referrerPubId) != Types.PublicationType.Mirror
127
- ) {
128
- revert Errors.InvalidReferrer();
129
- }
130
- Types.Publication storage _referrerMirror = StorageLib.getPublication(referrerProfileId, referrerPubId);
131
- // A mirror can only be a referrer of a legacy publication if it is pointing to it.
132
- if (
133
- _referrerMirror.pointedProfileId != publicationCollectedProfileId ||
134
- _referrerMirror.pointedPubId != publicationCollectedId
135
- ) {
136
- revert Errors.InvalidReferrer();
137
- }
138
- }
139
-
140
118
  function _validateReferrerAndGetReferrerPubType(
141
119
  uint256 referrerProfileId,
142
120
  uint256 referrerPubId,
@@ -17,7 +17,6 @@ library Errors {
17
17
  error NotProfileOwner();
18
18
  error PublicationDoesNotExist();
19
19
  error CallerNotFollowNFT();
20
- error CallerNotCollectNFT(); // Legacy
21
20
  error ArrayMismatch();
22
21
  error NotWhitelisted();
23
22
  error NotRegistered();
@@ -36,8 +35,6 @@ library Errors {
36
35
  error InitParamsInvalid();
37
36
  error ActionNotAllowed();
38
37
 
39
- error CollectNotAllowed(); // Used in LegacyCollectLib (pending deprecation)
40
-
41
38
  // MultiState Errors
42
39
  error Paused();
43
40
  error PublishingPaused();
@@ -225,20 +225,6 @@ library Events {
225
225
  * @param timestamp The current block timestamp.
226
226
  */
227
227
  event FollowNFTDeployed(uint256 indexed profileId, address indexed followNFT, uint256 timestamp);
228
- /**
229
- * @dev Emitted when a collectNFT clone is deployed using a lazy deployment pattern.
230
- *
231
- * @param profileId The publisher's profile token ID.
232
- * @param pubId The publication associated with the newly deployed collectNFT clone's ID.
233
- * @param collectNFT The address of the newly deployed collectNFT clone.
234
- * @param timestamp The current block timestamp.
235
- */
236
- event LegacyCollectNFTDeployed(
237
- uint256 indexed profileId,
238
- uint256 indexed pubId,
239
- address indexed collectNFT,
240
- uint256 timestamp
241
- );
242
228
  /**
243
229
  * @dev Emitted upon a successful action.
244
230
  *
@@ -8,8 +8,6 @@ library Typehash {
8
8
 
9
9
  bytes32 constant CHANGE_DELEGATED_EXECUTORS_CONFIG = keccak256('ChangeDelegatedExecutorsConfig(uint256 delegatorProfileId,address[] delegatedExecutors,bool[] approvals,uint64 configNumber,bool switchToGivenConfig,uint256 nonce,uint256 deadline)');
10
10
 
11
- bytes32 constant COLLECT_LEGACY = keccak256('CollectLegacy(uint256 publicationCollectedProfileId,uint256 publicationCollectedId,uint256 collectorProfileId,uint256 referrerProfileId,uint256 referrerPubId,bytes collectModuleData,uint256 nonce,uint256 deadline)');
12
-
13
11
  bytes32 constant COMMENT = keccak256('Comment(uint256 profileId,string contentURI,uint256 pointedProfileId,uint256 pointedPubId,uint256[] referrerProfileIds,uint256[] referrerPubIds,bytes referenceModuleData,address[] actionModules,bytes[] actionModulesInitDatas,address referenceModule,bytes referenceModuleInitData,uint256 nonce,uint256 deadline)');
14
12
 
15
13
  bytes32 constant EIP712_DOMAIN = keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)');
@@ -295,27 +295,6 @@ library Types {
295
295
  bytes referenceModuleData;
296
296
  }
297
297
 
298
- /**
299
- * Deprecated in V2: Will be removed after some time after upgrading to V2.
300
- * @notice A struct containing the parameters required for the legacy `collect()` function.
301
- * @dev The referrer can only be a mirror of the publication being collected.
302
- *
303
- * @param publicationCollectedProfileId The token ID of the profile that published the publication to collect.
304
- * @param publicationCollectedId The publication to collect's publication ID.
305
- * @param collectorProfileId The collector profile.
306
- * @param referrerProfileId The ID of a profile that authored a mirror that helped discovering the collected pub.
307
- * @param referrerPubId The ID of the mirror that helped discovering the collected pub.
308
- * @param collectModuleData The arbitrary data to pass to the collectModule if needed.
309
- */
310
- struct LegacyCollectParams {
311
- uint256 publicationCollectedProfileId;
312
- uint256 publicationCollectedId;
313
- uint256 collectorProfileId;
314
- uint256 referrerProfileId;
315
- uint256 referrerPubId;
316
- bytes collectModuleData;
317
- }
318
-
319
298
  /**
320
299
  * @notice A struct containing the parameters required for the `action()` function.
321
300
  *
@@ -24,10 +24,9 @@ contract LensHubInitializable is LensHub, VersionedInitializable, ILensHubInitia
24
24
 
25
25
  constructor(
26
26
  address followNFTImpl,
27
- address collectNFTImpl,
28
27
  address moduleRegistry,
29
28
  uint256 tokenGuardianCooldown
30
- ) LensHub(followNFTImpl, collectNFTImpl, moduleRegistry, tokenGuardianCooldown) {}
29
+ ) LensHub(followNFTImpl, moduleRegistry, tokenGuardianCooldown) {}
31
30
 
32
31
  /**
33
32
  * @inheritdoc ILensHubInitializable
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lens-modules",
3
- "version": "1.1.3",
3
+ "version": "1.2.0",
4
4
  "description": "All interfaces and base classes from Lens core used for creating follow, collect, and open action modules",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,45 +0,0 @@
1
- // SPDX-License-Identifier: MIT
2
-
3
- pragma solidity >=0.6.0;
4
-
5
- /**
6
- * @title ICollectModule
7
- * @author Lens Protocol
8
- * @custom:pending-deprecation
9
- *
10
- * @notice This is the deprecated interface for previously Lens-compatible CollectModules.
11
- */
12
- interface ILegacyCollectModule {
13
- /**
14
- * @notice Initializes data for a given publication being published. This can only be called by the hub.
15
- *
16
- * @param profileId The token ID of the profile publishing the publication.
17
- * @param pubId The associated publication's LensHub publication ID.
18
- * @param data Arbitrary data __passed from the user!__ to be decoded.
19
- *
20
- * @return bytes An ABI-encoded encapsulating the execution's state changes. This will be emitted by the
21
- * hub alongside the collect module's address and should be consumed by front ends.
22
- */
23
- function initializePublicationCollectModule(
24
- uint256 profileId,
25
- uint256 pubId,
26
- bytes calldata data
27
- ) external returns (bytes memory);
28
-
29
- /**
30
- * @notice Processes a collect action for a given publication, this can only be called by the hub.
31
- *
32
- * @param referrerProfileId The LensHub profile token ID of the referrer's profile (only different in case of mirrors).
33
- * @param collector The collector address.
34
- * @param profileId The token ID of the profile associated with the publication being collected.
35
- * @param pubId The LensHub publication ID associated with the publication being collected.
36
- * @param data Arbitrary data __passed from the collector!__ to be decoded.
37
- */
38
- function processCollect(
39
- uint256 referrerProfileId,
40
- address collector,
41
- uint256 profileId,
42
- uint256 pubId,
43
- bytes calldata data
44
- ) external;
45
- }
@@ -1,46 +0,0 @@
1
- // SPDX-License-Identifier: MIT
2
-
3
- pragma solidity >=0.6.0;
4
-
5
- /**
6
- * @title ILegacyCollectNFT
7
- * @author Lens Protocol
8
- *
9
- * @notice This is the interface for the Lens V1 CollectNFT contract. Which is cloned upon the first collect for any
10
- * given publication.
11
- */
12
- interface ILegacyCollectNFT {
13
- /**
14
- * @notice Initializes the collect NFT, setting the feed as the privileged minter, storing the collected publication
15
- * pointer and initializing the name and symbol in the LensNFTBase contract.
16
- * @custom:permissions LensHub.
17
- *
18
- * @param profileId The token ID of the profile in the hub that this Collect NFT points to.
19
- * @param pubId The profile publication ID in the hub that this Collect NFT points to.
20
- * @param name The name to set for this NFT.
21
- * @param symbol The symbol to set for this NFT.
22
- */
23
- function initialize(
24
- uint256 profileId,
25
- uint256 pubId,
26
- string calldata name,
27
- string calldata symbol
28
- ) external;
29
-
30
- /**
31
- * @notice Mints a collect NFT to the specified address.
32
- * @custom:permissions LensHub.
33
- *
34
- * @param to The address to mint the NFT to.
35
- *
36
- * @return uint256 An integer representing the minted token ID.
37
- */
38
- function mint(address to) external returns (uint256);
39
-
40
- /**
41
- * @notice Returns the source publication of this collect NFT.
42
- *
43
- * @return tuple First is the profile ID, and second is the publication ID.
44
- */
45
- function getSourcePublicationPointer() external view returns (uint256, uint256);
46
- }
@@ -1,82 +0,0 @@
1
- // SPDX-License-Identifier: MIT
2
-
3
- pragma solidity ^0.8.15;
4
-
5
- /**
6
- * @title IFollowModule
7
- * @author Lens Protocol
8
- *
9
- * @notice This is the deprecated interface for previously Lens-compatible FollowModules.
10
- */
11
- interface ILegacyFollowModule {
12
- /**
13
- * @notice Initializes a follow module for a given Lens profile. This can only be called by the hub contract.
14
- *
15
- * @param profileId The token ID of the profile to initialize this follow module for.
16
- * @param data Arbitrary data passed by the profile creator.
17
- *
18
- * @return bytes The encoded data to emit in the hub.
19
- */
20
- function initializeFollowModule(uint256 profileId, bytes calldata data) external returns (bytes memory);
21
-
22
- /**
23
- * @notice Processes a given follow, this can only be called from the LensHub contract.
24
- *
25
- * @param follower The follower address.
26
- * @param profileId The token ID of the profile being followed.
27
- * @param data Arbitrary data passed by the follower.
28
- */
29
- function processFollow(
30
- address follower,
31
- uint256 profileId,
32
- bytes calldata data
33
- ) external;
34
-
35
- /**
36
- * @notice This is a transfer hook that is called upon follow NFT transfer in `beforeTokenTransfer. This can
37
- * only be called from the LensHub contract.
38
- *
39
- * NOTE: Special care needs to be taken here: It is possible that follow NFTs were issued before this module
40
- * was initialized if the profile's follow module was previously different. This transfer hook should take this
41
- * into consideration, especially when the module holds a state associated with individual follow NFTs.
42
- *
43
- * @param profileId The token ID of the profile associated with the follow NFT being transferred.
44
- * @param from The address sending the follow NFT.
45
- * @param to The address receiving the follow NFT.
46
- * @param followNFTTokenId The token ID of the follow NFT being transferred.
47
- */
48
- function followModuleTransferHook(
49
- uint256 profileId,
50
- address from,
51
- address to,
52
- uint256 followNFTTokenId
53
- ) external;
54
-
55
- /**
56
- * @notice This is a helper function that could be used in conjunction with specific collect modules.
57
- *
58
- * NOTE: This function IS meant to replace a check on follower NFT ownership.
59
- *
60
- * NOTE: It is assumed that not all collect modules are aware of the token ID to pass. In these cases,
61
- * this should receive a `followNFTTokenId` of 0, which is impossible regardless.
62
- *
63
- * One example of a use case for this would be a subscription-based following system:
64
- * 1. The collect module:
65
- * - Decodes a follower NFT token ID from user-passed data.
66
- * - Fetches the follow module from the hub.
67
- * - Calls `isFollowing` passing the profile ID, follower & follower token ID and checks it returned true.
68
- * 2. The follow module:
69
- * - Validates the subscription status for that given NFT, reverting on an invalid subscription.
70
- *
71
- * @param profileId The token ID of the profile to validate the follow for.
72
- * @param follower The follower address to validate the follow for.
73
- * @param followNFTTokenId The followNFT token ID to validate the follow for.
74
- *
75
- * @return true if the given address is following the given profile ID, false otherwise.
76
- */
77
- function isFollowing(
78
- uint256 profileId,
79
- address follower,
80
- uint256 followNFTTokenId
81
- ) external view returns (bool);
82
- }
@@ -1,58 +0,0 @@
1
- // SPDX-License-Identifier: MIT
2
-
3
- pragma solidity >=0.6.0;
4
-
5
- /**
6
- * @title IReferenceModule
7
- * @author Lens Protocol
8
- * @custom:pending-deprecation
9
- *
10
- * @notice This is the deprecated interface for previously Lens-compatible ReferenceModules.
11
- */
12
- interface ILegacyReferenceModule {
13
- /**
14
- * @notice Initializes data for a given publication being published. This can only be called by the hub.
15
- *
16
- * @param profileId The token ID of the profile publishing the publication.
17
- * @param pubId The associated publication's LensHub publication ID.
18
- * @param data Arbitrary data passed from the user to be decoded.
19
- *
20
- * @return bytes An ABI-encoded data encapsulating the execution's state changes. This will be emitted by the
21
- * hub alongside the collect module's address and should be consumed by front ends.
22
- */
23
- function initializeReferenceModule(
24
- uint256 profileId,
25
- uint256 pubId,
26
- bytes calldata data
27
- ) external returns (bytes memory);
28
-
29
- /**
30
- * @notice Processes a comment action referencing a given publication. This can only be called by the hub.
31
- *
32
- * @param profileId The token ID of the profile associated with the publication being published.
33
- * @param pointedProfileId The profile ID of the profile associated with the publication being referenced.
34
- * @param pointedPubId The publication ID of the publication being referenced.
35
- * @param data Arbitrary data __passed from the commenter!__ to be decoded.
36
- */
37
- function processComment(
38
- uint256 profileId,
39
- uint256 pointedProfileId,
40
- uint256 pointedPubId,
41
- bytes calldata data
42
- ) external;
43
-
44
- /**
45
- * @notice Processes a mirror action referencing a given publication. This can only be called by the hub.
46
- *
47
- * @param profileId The token ID of the profile associated with the publication being published.
48
- * @param pointedProfileId The profile ID of the profile associated with the publication being referenced.
49
- * @param pointedPubId The publication ID of the publication being referenced.
50
- * @param data Arbitrary data __passed from the mirrorer!__ to be decoded.
51
- */
52
- function processMirror(
53
- uint256 profileId,
54
- uint256 pointedProfileId,
55
- uint256 pointedPubId,
56
- bytes calldata data
57
- ) external;
58
- }
@@ -1,176 +0,0 @@
1
- // SPDX-License-Identifier: MIT
2
-
3
- pragma solidity ^0.8.15;
4
-
5
- import {ValidationLib} from './ValidationLib.sol';
6
- import {Types} from './constants/Types.sol';
7
- import {Errors} from './constants/Errors.sol';
8
- import {Events} from './constants/Events.sol';
9
- import {ICollectNFT} from '../interfaces/ICollectNFT.sol';
10
- import {ILegacyCollectModule} from '../interfaces/ILegacyCollectModule.sol';
11
- import {Clones} from '@openzeppelin/contracts/proxy/Clones.sol';
12
- import {Strings} from '@openzeppelin/contracts/utils/Strings.sol';
13
- import {StorageLib} from './StorageLib.sol';
14
- import {FollowLib} from './FollowLib.sol';
15
-
16
- /**
17
- * @title LegacyCollectLib
18
- * @author Lens Protocol
19
- * @notice Library containing the logic for legacy collect operation.
20
- */
21
- library LegacyCollectLib {
22
- using Strings for uint256;
23
-
24
- /**
25
- * @dev Emitted upon a successful legacy collect action.
26
- *
27
- * @param publicationCollectedProfileId The profile ID of the publication being collected.
28
- * @param publicationCollectedId The publication ID of the publication being collected.
29
- * @param collectorProfileId The profile ID of the profile that collected the publication.
30
- * @param transactionExecutor The address of the account that executed the collect transaction.
31
- * @param referrerProfileId The profile ID of the referrer, if any. Zero if no referrer.
32
- * @param referrerPubId The publication ID of the referrer, if any. Zero if no referrer.
33
- * @param collectModule The address of the collect module that was used to collect the publication.
34
- * @param collectModuleData The data passed to the collect module's collect action. This is ABI-encoded and depends
35
- * on the collect module chosen.
36
- * @param tokenId The token ID of the collect NFT that was minted as a collect of the publication.
37
- * @param timestamp The current block timestamp.
38
- */
39
- event CollectedLegacy(
40
- uint256 indexed publicationCollectedProfileId,
41
- uint256 indexed publicationCollectedId,
42
- uint256 indexed collectorProfileId,
43
- address transactionExecutor,
44
- uint256 referrerProfileId,
45
- uint256 referrerPubId,
46
- address collectModule,
47
- bytes collectModuleData,
48
- uint256 tokenId,
49
- uint256 timestamp
50
- );
51
-
52
- function collect(
53
- Types.LegacyCollectParams calldata collectParams,
54
- address transactionExecutor,
55
- address collectorProfileOwner,
56
- address collectNFTImpl
57
- ) external returns (uint256) {
58
- ValidationLib.validateNotBlocked({
59
- profile: collectParams.collectorProfileId,
60
- byProfile: collectParams.publicationCollectedProfileId
61
- });
62
-
63
- address collectModule;
64
- uint256 tokenId;
65
- address collectNFT;
66
- {
67
- Types.Publication storage _collectedPublication = StorageLib.getPublication(
68
- collectParams.publicationCollectedProfileId,
69
- collectParams.publicationCollectedId
70
- );
71
- // This is a legacy collect operation, so we get the collect module from the deprecated storage field.
72
- collectModule = _collectedPublication.__DEPRECATED__collectModule;
73
- if (collectModule == address(0)) {
74
- // It doesn't have collect module, thus it cannot be collected (a mirror or non-existent).
75
- revert Errors.CollectNotAllowed();
76
- }
77
-
78
- if (collectParams.referrerProfileId != 0 || collectParams.referrerPubId != 0) {
79
- ValidationLib.validateLegacyCollectReferrer(
80
- collectParams.referrerProfileId,
81
- collectParams.referrerPubId,
82
- collectParams.publicationCollectedProfileId,
83
- collectParams.publicationCollectedId
84
- );
85
- }
86
-
87
- collectNFT = _getOrDeployCollectNFT(
88
- _collectedPublication,
89
- collectParams.publicationCollectedProfileId,
90
- collectParams.publicationCollectedId,
91
- collectNFTImpl
92
- );
93
- tokenId = ICollectNFT(collectNFT).mint(collectorProfileOwner);
94
- }
95
-
96
- _prefillLegacyCollectFollowValidationHelper({
97
- profileId: collectParams.publicationCollectedProfileId,
98
- collectorProfileId: collectParams.collectorProfileId,
99
- collector: transactionExecutor
100
- });
101
-
102
- ILegacyCollectModule(collectModule).processCollect({
103
- // Legacy collect modules expect referrer profile ID to match the collected pub's author if no referrer set.
104
- referrerProfileId: collectParams.referrerProfileId == 0
105
- ? collectParams.publicationCollectedProfileId
106
- : collectParams.referrerProfileId,
107
- // Collect NFT is minted to the `collectorProfileOwner`. Some follow-based constraints are expected to be
108
- // broken in legacy collect modules if the `transactionExecutor` does not match the `collectorProfileOwner`.
109
- collector: transactionExecutor,
110
- profileId: collectParams.publicationCollectedProfileId,
111
- pubId: collectParams.publicationCollectedId,
112
- data: collectParams.collectModuleData
113
- });
114
-
115
- emit CollectedLegacy({
116
- publicationCollectedProfileId: collectParams.publicationCollectedProfileId,
117
- publicationCollectedId: collectParams.publicationCollectedId,
118
- collectorProfileId: collectParams.collectorProfileId,
119
- transactionExecutor: transactionExecutor,
120
- referrerProfileId: collectParams.referrerProfileId,
121
- referrerPubId: collectParams.referrerPubId,
122
- collectModule: collectModule,
123
- collectModuleData: collectParams.collectModuleData,
124
- tokenId: tokenId,
125
- timestamp: block.timestamp
126
- });
127
-
128
- return tokenId;
129
- }
130
-
131
- function _getOrDeployCollectNFT(
132
- Types.Publication storage _collectedPublication,
133
- uint256 publicationCollectedProfileId,
134
- uint256 publicationCollectedId,
135
- address collectNFTImpl
136
- ) private returns (address) {
137
- address collectNFT = _collectedPublication.__DEPRECATED__collectNFT;
138
- if (collectNFT == address(0)) {
139
- collectNFT = _deployCollectNFT(publicationCollectedProfileId, publicationCollectedId, collectNFTImpl);
140
- _collectedPublication.__DEPRECATED__collectNFT = collectNFT;
141
- }
142
- return collectNFT;
143
- }
144
-
145
- /**
146
- * @notice Deploys the given profile's Collect NFT contract.
147
- *
148
- * @param profileId The token ID of the profile which Collect NFT should be deployed.
149
- * @param pubId The publication ID of the publication being collected, which Collect NFT should be deployed.
150
- * @param collectNFTImpl The address of the Collect NFT implementation that should be used for the deployment.
151
- *
152
- * @return address The address of the deployed Collect NFT contract.
153
- */
154
- function _deployCollectNFT(uint256 profileId, uint256 pubId, address collectNFTImpl) private returns (address) {
155
- address collectNFT = Clones.clone(collectNFTImpl);
156
-
157
- ICollectNFT(collectNFT).initialize(profileId, pubId);
158
- emit Events.LegacyCollectNFTDeployed(profileId, pubId, collectNFT, block.timestamp);
159
-
160
- return collectNFT;
161
- }
162
-
163
- function _prefillLegacyCollectFollowValidationHelper(
164
- uint256 profileId,
165
- uint256 collectorProfileId,
166
- address collector
167
- ) private {
168
- // It's important to set it as zero if not following, as the storage could be dirty from a previous transaction.
169
- StorageLib.legacyCollectFollowValidationHelper()[collector] = FollowLib.isFollowing({
170
- followerProfileId: collectorProfileId,
171
- followedProfileId: profileId
172
- })
173
- ? profileId
174
- : 0;
175
- }
176
- }
@@ -1,126 +0,0 @@
1
- // SPDX-License-Identifier: MIT
2
-
3
- pragma solidity ^0.8.15;
4
-
5
- import {ERC2981CollectionRoyalties} from '../base/ERC2981CollectionRoyalties.sol';
6
- import {Errors} from '../libraries/constants/Errors.sol';
7
- import {ICollectNFT} from '../interfaces/ICollectNFT.sol';
8
- import {IERC721} from '@openzeppelin/contracts/token/ERC721/IERC721.sol';
9
- import {ILensHub} from '../interfaces/ILensHub.sol';
10
- import {LensBaseERC721} from '../base/LensBaseERC721.sol';
11
- import {Strings} from '@openzeppelin/contracts/utils/Strings.sol';
12
-
13
- /**
14
- * @title CollectNFT
15
- * @author Lens Protocol
16
- *
17
- * @dev This is the Legacy CollectNFT that is used for Legacy Lens V1 publications. The new CollectNFT was introduced in
18
- * Lens V2 with the only difference that it is restricted by the Action Module instead of the LensHub.
19
- *
20
- * @notice This is the NFT contract that is minted upon collecting a given publication. It is cloned upon
21
- * the first collect for a given publication, and the token URI points to the original publication's contentURI.
22
- */
23
- contract LegacyCollectNFT is LensBaseERC721, ERC2981CollectionRoyalties, ICollectNFT {
24
- using Strings for uint256;
25
-
26
- address public immutable HUB;
27
-
28
- uint256 internal _profileId;
29
- uint256 internal _pubId;
30
- uint256 internal _tokenIdCounter;
31
-
32
- bool private _initialized;
33
-
34
- uint256 internal _royaltiesInBasisPoints;
35
-
36
- // We create the CollectNFT with the pre-computed HUB address before deploying the hub proxy in order
37
- // to initialize the hub proxy at construction.
38
- constructor(address hub) {
39
- if (hub == address(0)) revert Errors.InitParamsInvalid();
40
- HUB = hub;
41
- _initialized = true;
42
- }
43
-
44
- /// @inheritdoc ICollectNFT
45
- function initialize(uint256 profileId, uint256 pubId) external override {
46
- if (_initialized) revert Errors.Initialized();
47
- _initialized = true;
48
- _setRoyalty(1000); // 10% of royalties
49
- _profileId = profileId;
50
- _pubId = pubId;
51
- // _name and _symbol remain uninitialized because we override the getters below
52
- }
53
-
54
- /// @inheritdoc ICollectNFT
55
- function mint(address to) external override returns (uint256) {
56
- if (msg.sender != HUB) revert Errors.NotHub();
57
- unchecked {
58
- uint256 tokenId = ++_tokenIdCounter;
59
- _mint(to, tokenId);
60
- return tokenId;
61
- }
62
- }
63
-
64
- /// @inheritdoc ICollectNFT
65
- function getSourcePublicationPointer() external view override returns (uint256, uint256) {
66
- return (_profileId, _pubId);
67
- }
68
-
69
- function tokenURI(uint256 tokenId) public view override returns (string memory) {
70
- if (!_exists(tokenId)) revert Errors.TokenDoesNotExist();
71
- return ILensHub(HUB).getContentURI(_profileId, _pubId);
72
- }
73
-
74
- /**
75
- * @dev See {IERC721Metadata-name}.
76
- */
77
- function name() public view override returns (string memory) {
78
- return string.concat('Lens Collect | Profile #', _profileId.toString(), ' - Publication #', _pubId.toString());
79
- }
80
-
81
- /**
82
- * @dev See {IERC721Metadata-symbol}.
83
- */
84
- function symbol() public pure override returns (string memory) {
85
- return 'LENS-COLLECT';
86
- }
87
-
88
- /**
89
- * @dev See {IERC165-supportsInterface}.
90
- */
91
- function supportsInterface(bytes4 interfaceId)
92
- public
93
- view
94
- virtual
95
- override(ERC2981CollectionRoyalties, LensBaseERC721)
96
- returns (bool)
97
- {
98
- return
99
- ERC2981CollectionRoyalties.supportsInterface(interfaceId) || LensBaseERC721.supportsInterface(interfaceId);
100
- }
101
-
102
- function _getReceiver(
103
- uint256 /* tokenId */
104
- ) internal view override returns (address) {
105
- if (!ILensHub(HUB).exists(_profileId)) {
106
- return address(0);
107
- }
108
- return IERC721(HUB).ownerOf(_profileId);
109
- }
110
-
111
- function _beforeRoyaltiesSet(
112
- uint256 /* royaltiesInBasisPoints */
113
- ) internal view override {
114
- if (IERC721(HUB).ownerOf(_profileId) != msg.sender) {
115
- revert Errors.NotProfileOwner();
116
- }
117
- }
118
-
119
- function _getRoyaltiesInBasisPointsSlot() internal pure override returns (uint256) {
120
- uint256 slot;
121
- assembly {
122
- slot := _royaltiesInBasisPoints.slot
123
- }
124
- return slot;
125
- }
126
- }