lens-modules 1.1.2 → 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.
- package/contracts/LensHub.sol +2 -67
- package/contracts/base/LensHubEventHooks.sol +0 -19
- package/contracts/base/LensImplGetters.sol +1 -8
- package/contracts/interfaces/ILensImplGetters.sol +0 -8
- package/contracts/interfaces/ILensProtocol.sol +0 -22
- package/contracts/libraries/MetaTxLib.sol +0 -24
- package/contracts/libraries/PublicationLib.sol +39 -109
- package/contracts/libraries/ValidationLib.sol +0 -22
- package/contracts/libraries/constants/Errors.sol +0 -3
- package/contracts/libraries/constants/Events.sol +0 -14
- package/contracts/libraries/constants/Typehash.sol +2 -2
- package/contracts/libraries/constants/Types.sol +0 -21
- package/contracts/misc/LensHubInitializable.sol +1 -2
- package/contracts/misc/PublicActProxy.sol +1 -1
- package/contracts/namespaces/constants/Typehash.sol +3 -25
- package/package.json +1 -1
- package/contracts/interfaces/ILegacyCollectModule.sol +0 -45
- package/contracts/interfaces/ILegacyCollectNFT.sol +0 -46
- package/contracts/interfaces/ILegacyFollowModule.sol +0 -82
- package/contracts/interfaces/ILegacyReferenceModule.sol +0 -58
- package/contracts/libraries/LegacyCollectLib.sol +0 -176
- package/contracts/misc/LegacyCollectNFT.sol +0 -126
package/contracts/LensHub.sol
CHANGED
|
@@ -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,
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
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
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
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
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
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)');
|
|
@@ -29,4 +27,6 @@ library Typehash {
|
|
|
29
27
|
bytes32 constant SET_PROFILE_METADATA_URI = keccak256('SetProfileMetadataURI(uint256 profileId,string metadataURI,uint256 nonce,uint256 deadline)');
|
|
30
28
|
|
|
31
29
|
bytes32 constant UNFOLLOW = keccak256('Unfollow(uint256 unfollowerProfileId,uint256[] idsOfProfilesToUnfollow,uint256 nonce,uint256 deadline)');
|
|
30
|
+
|
|
31
|
+
bytes32 constant PUBLIC_PAID_ACT = keccak256('PublicPaidAct(uint256 publicationActedProfileId,uint256 publicationActedId,uint256 actorProfileId,uint256[] referrerProfileIds,uint256[] referrerPubIds,address actionModuleAddress,bytes actionModuleData,address currency,uint256 amount,address approveTo,uint256 nonce,uint256 deadline)');
|
|
32
32
|
}
|
|
@@ -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,
|
|
29
|
+
) LensHub(followNFTImpl, moduleRegistry, tokenGuardianCooldown) {}
|
|
31
30
|
|
|
32
31
|
/**
|
|
33
32
|
* @inheritdoc ILensHubInitializable
|
|
@@ -7,7 +7,7 @@ import {Types} from '../libraries/constants/Types.sol';
|
|
|
7
7
|
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
|
|
8
8
|
import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
|
|
9
9
|
import {CollectPublicationAction} from '../modules/act/collect/CollectPublicationAction.sol';
|
|
10
|
-
import {PublicActProxy_MetaTx} from '
|
|
10
|
+
import {PublicActProxy_MetaTx} from '../misc/PublicActProxy_MetaTx.sol';
|
|
11
11
|
|
|
12
12
|
// This contract should be the owner/DE of the publicationActionParams.actorProfileId
|
|
13
13
|
// This contract should be set as publicationActionParams.transactionExecutor
|
|
@@ -4,31 +4,9 @@ pragma solidity >=0.6.0;
|
|
|
4
4
|
|
|
5
5
|
library Typehash {
|
|
6
6
|
|
|
7
|
-
bytes32 constant ACT = keccak256('Act(uint256 publicationActedProfileId,uint256 publicationActedId,uint256 actorProfileId,uint256[] referrerProfileIds,uint256[] referrerPubIds,address actionModuleAddress,bytes actionModuleData,uint256 nonce,uint256 deadline)');
|
|
8
|
-
|
|
9
|
-
bytes32 constant CHANGE_DELEGATED_EXECUTORS_CONFIG = keccak256('ChangeDelegatedExecutorsConfig(uint256 delegatorProfileId,address[] delegatedExecutors,bool[] approvals,uint64 configNumber,bool switchToGivenConfig,uint256 nonce,uint256 deadline)');
|
|
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
|
-
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
|
-
|
|
15
7
|
bytes32 constant EIP712_DOMAIN = keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)');
|
|
16
8
|
|
|
17
|
-
bytes32 constant
|
|
18
|
-
|
|
19
|
-
bytes32 constant MIRROR = keccak256('Mirror(uint256 profileId,string metadataURI,uint256 pointedProfileId,uint256 pointedPubId,uint256[] referrerProfileIds,uint256[] referrerPubIds,bytes referenceModuleData,uint256 nonce,uint256 deadline)');
|
|
20
|
-
|
|
21
|
-
bytes32 constant POST = keccak256('Post(uint256 profileId,string contentURI,address[] actionModules,bytes[] actionModulesInitDatas,address referenceModule,bytes referenceModuleInitData,uint256 nonce,uint256 deadline)');
|
|
22
|
-
|
|
23
|
-
bytes32 constant QUOTE = keccak256('Quote(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)');
|
|
24
|
-
|
|
25
|
-
bytes32 constant SET_BLOCK_STATUS = keccak256('SetBlockStatus(uint256 byProfileId,uint256[] idsOfProfilesToSetBlockStatus,bool[] blockStatus,uint256 nonce,uint256 deadline)');
|
|
26
|
-
|
|
27
|
-
bytes32 constant SET_FOLLOW_MODULE = keccak256('SetFollowModule(uint256 profileId,address followModule,bytes followModuleInitData,uint256 nonce,uint256 deadline)');
|
|
28
|
-
|
|
29
|
-
bytes32 constant SET_PROFILE_METADATA_URI = keccak256('SetProfileMetadataURI(uint256 profileId,string metadataURI,uint256 nonce,uint256 deadline)');
|
|
30
|
-
|
|
31
|
-
bytes32 constant UNFOLLOW = keccak256('Unfollow(uint256 unfollowerProfileId,uint256[] idsOfProfilesToUnfollow,uint256 nonce,uint256 deadline)');
|
|
9
|
+
bytes32 constant LINK = keccak256('Link(uint256 handleId,uint256 profileId,uint256 nonce,uint256 deadline)');
|
|
32
10
|
|
|
33
|
-
bytes32 constant
|
|
34
|
-
}
|
|
11
|
+
bytes32 constant UNLINK = keccak256('Unlink(uint256 handleId,uint256 profileId,uint256 nonce,uint256 deadline)');
|
|
12
|
+
}
|
package/package.json
CHANGED
|
@@ -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
|
-
}
|