Merge pull request #68 from lens-protocol/fix/referral-system

fix: Referral system
This commit is contained in:
Alan
2023-04-20 21:35:23 +01:00
committed by GitHub
11 changed files with 249 additions and 257 deletions

View File

@@ -22,7 +22,7 @@ import {LensHubEventHooks} from 'contracts/base/LensHubEventHooks.sol';
// Libraries
import {ActionLib} from 'contracts/libraries/ActionLib.sol';
import {CollectLib} from 'contracts/libraries/CollectLib.sol';
import {LegacyCollectLib} from 'contracts/libraries/LegacyCollectLib.sol';
import {FollowLib} from 'contracts/libraries/FollowLib.sol';
import {GovernanceLib} from 'contracts/libraries/GovernanceLib.sol';
import {MetaTxLib} from 'contracts/libraries/MetaTxLib.sol';
@@ -440,7 +440,7 @@ contract LensHub is
returns (uint256)
{
return
CollectLib.collect({
LegacyCollectLib.collect({
collectParams: collectParams,
transactionExecutor: msg.sender,
collectorProfileOwner: ownerOf(collectParams.collectorProfileId),
@@ -459,9 +459,9 @@ contract LensHub is
onlyProfileOwnerOrDelegatedExecutor(signature.signer, collectParams.collectorProfileId)
returns (uint256)
{
MetaTxLib.validateCollectSignature(signature, collectParams);
MetaTxLib.validateLegacyCollectSignature(signature, collectParams);
return
CollectLib.collect({
LegacyCollectLib.collect({
collectParams: collectParams,
transactionExecutor: signature.signer,
collectorProfileOwner: ownerOf(collectParams.collectorProfileId),

View File

@@ -1,193 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
import {ValidationLib} from 'contracts/libraries/ValidationLib.sol';
import {Types} from 'contracts/libraries/constants/Types.sol';
import {Errors} from 'contracts/libraries/constants/Errors.sol';
import {Events} from 'contracts/libraries/constants/Events.sol';
import {ICollectNFT} from 'contracts/interfaces/ICollectNFT.sol';
import {ICollectModule} from 'contracts/interfaces/ICollectModule.sol';
import {ILegacyCollectModule} from 'contracts/interfaces/ILegacyCollectModule.sol';
import {Clones} from '@openzeppelin/contracts/proxy/Clones.sol';
import {Strings} from '@openzeppelin/contracts/utils/Strings.sol';
import {StorageLib} from 'contracts/libraries/StorageLib.sol';
/**
* @title CollectLib
* @author Lens Protocol
*/
library CollectLib {
using Strings for uint256;
string constant COLLECT_NFT_NAME_INFIX = '-Collect-';
string constant COLLECT_NFT_SYMBOL_INFIX = '-Cl-';
function collect(
Types.CollectParams calldata collectParams,
address transactionExecutor,
address collectorProfileOwner,
address collectNFTImpl
) external returns (uint256) {
ValidationLib.validateNotBlocked({
profile: collectParams.collectorProfileId,
byProfile: collectParams.publicationCollectedProfileId
});
address collectModule;
Types.PublicationType[] memory referrerPubTypes;
uint256 tokenId;
address collectNFT;
{
Types.Publication storage _collectedPublication = StorageLib.getPublication(
collectParams.publicationCollectedProfileId,
collectParams.publicationCollectedId
);
collectModule = _collectedPublication.__DEPRECATED__collectModule;
if (collectModule == address(0)) {
// Doesn't have collectModule, thus it cannot be collected (a mirror or non-existent).
revert Errors.CollectNotAllowed();
}
referrerPubTypes = ValidationLib.validateReferrersAndGetReferrersPubTypes(
collectParams.referrerProfileIds,
collectParams.referrerPubIds,
collectParams.publicationCollectedProfileId,
collectParams.publicationCollectedId
);
collectNFT = _getOrDeployCollectNFT(
_collectedPublication,
collectParams.publicationCollectedProfileId,
collectParams.publicationCollectedId,
collectNFTImpl
);
tokenId = ICollectNFT(collectNFT).mint(collectorProfileOwner);
}
_processCollect(
collectParams,
ProcessCollectParams({
transactionExecutor: transactionExecutor,
collectorProfileOwner: collectorProfileOwner,
referrerPubTypes: referrerPubTypes,
collectModule: collectModule
})
);
emit Events.Collected({
collectActionParams: Types.ProcessActionParams({
publicationActedProfileId: collectParams.publicationCollectedProfileId,
publicationActedId: collectParams.publicationCollectedId,
actorProfileId: collectParams.collectorProfileId,
actorProfileOwner: collectorProfileOwner,
transactionExecutor: transactionExecutor,
referrerProfileIds: collectParams.referrerProfileIds,
referrerPubIds: collectParams.referrerPubIds,
referrerPubTypes: referrerPubTypes,
actionModuleData: collectParams.collectModuleData
}),
collectModule: collectModule,
collectNFT: collectNFT,
tokenId: tokenId,
collectActionResult: '',
timestamp: block.timestamp
});
return tokenId;
}
function _getOrDeployCollectNFT(
Types.Publication storage _collectedPublication,
uint256 publicationCollectedProfileId,
uint256 publicationCollectedId,
address collectNFTImpl
) private returns (address) {
address collectNFT = _collectedPublication.__DEPRECATED__collectNFT;
if (collectNFT == address(0)) {
collectNFT = _deployCollectNFT(publicationCollectedProfileId, publicationCollectedId, collectNFTImpl);
_collectedPublication.__DEPRECATED__collectNFT = collectNFT;
}
return collectNFT;
}
// Stack too deep, so we need to use a struct.
struct ProcessCollectParams {
address transactionExecutor;
address collectorProfileOwner;
Types.PublicationType[] referrerPubTypes;
address collectModule;
}
function _processCollect(
Types.CollectParams calldata collectParams,
ProcessCollectParams memory processCollectParams
) private {
try
ICollectModule(processCollectParams.collectModule).processCollect(
Types.ProcessCollectParams({
publicationCollectedProfileId: collectParams.publicationCollectedProfileId,
publicationCollectedId: collectParams.publicationCollectedId,
collectorProfileId: collectParams.collectorProfileId,
collectorProfileOwner: processCollectParams.collectorProfileOwner,
transactionExecutor: processCollectParams.transactionExecutor,
referrerProfileIds: collectParams.referrerProfileIds,
referrerPubIds: collectParams.referrerPubIds,
referrerPubTypes: processCollectParams.referrerPubTypes,
data: collectParams.collectModuleData
})
)
{} catch (bytes memory err) {
assembly {
// Equivalent to reverting with the returned error selector if
// the length is not zero.
let length := mload(err)
if iszero(iszero(length)) {
revert(add(err, 32), length)
}
}
uint256 referrerProfileId;
uint256 referrerPubId;
if (collectParams.referrerProfileIds.length > 0) {
if (collectParams.referrerProfileIds.length > 1) {
// Deprecated modules only support one referrer.
revert Errors.DeprecaredModulesOnlySupportOneReferrer();
}
// Only one referral was passed.
referrerProfileId = collectParams.referrerProfileIds[0];
referrerPubId = collectParams.referrerPubIds[0];
}
ILegacyCollectModule(processCollectParams.collectModule).processCollect(
collectParams.publicationCollectedProfileId,
processCollectParams.transactionExecutor,
referrerProfileId,
referrerPubId,
collectParams.collectModuleData
);
}
}
/**
* @notice Deploys the given profile's Collect NFT contract.
*
* @param profileId The token ID of the profile which Collect NFT should be deployed.
* @param pubId The publication ID of the publication being collected, which Collect NFT should be deployed.
* @param collectNFTImpl The address of the Collect NFT implementation that should be used for the deployment.
*
* @return address The address of the deployed Collect NFT contract.
*/
function _deployCollectNFT(uint256 profileId, uint256 pubId, address collectNFTImpl) private returns (address) {
address collectNFT = Clones.clone(collectNFTImpl);
string memory collectNFTName = string(
abi.encodePacked(profileId.toString(), COLLECT_NFT_NAME_INFIX, pubId.toString())
);
string memory collectNFTSymbol = string(
abi.encodePacked(profileId.toString(), COLLECT_NFT_SYMBOL_INFIX, pubId.toString())
);
ICollectNFT(collectNFT).initialize(profileId, pubId, collectNFTName, collectNFTSymbol);
emit Events.CollectNFTDeployed(profileId, pubId, collectNFT, block.timestamp);
return collectNFT;
}
}

View File

@@ -0,0 +1,158 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
import {ValidationLib} from 'contracts/libraries/ValidationLib.sol';
import {Types} from 'contracts/libraries/constants/Types.sol';
import {Errors} from 'contracts/libraries/constants/Errors.sol';
import {Events} from 'contracts/libraries/constants/Events.sol';
import {ICollectNFT} from 'contracts/interfaces/ICollectNFT.sol';
import {ICollectModule} from 'contracts/interfaces/ICollectModule.sol';
import {ILegacyCollectModule} from 'contracts/interfaces/ILegacyCollectModule.sol';
import {Clones} from '@openzeppelin/contracts/proxy/Clones.sol';
import {Strings} from '@openzeppelin/contracts/utils/Strings.sol';
import {StorageLib} from 'contracts/libraries/StorageLib.sol';
import {PublicationLib} from 'contracts/libraries/PublicationLib.sol';
/**
* @title LegacyCollectLib
* @author Lens Protocol
* @notice Library containing the logic for legacy collect operation.
*/
library LegacyCollectLib {
using Strings for uint256;
string constant COLLECT_NFT_NAME_INFIX = '-Collect-';
string constant COLLECT_NFT_SYMBOL_INFIX = '-Cl-';
/**
* @dev Emitted upon a successful legacy collect action.
*
* @param publicationCollectedProfileId The profile ID of the publication being collected.
* @param publicationCollectedId The publication ID of the publication being collected.
* @param transactionExecutor The address of the account that executed the collect transaction.
* @param referrerProfileId The profile ID of the referrer, if any. Zero if no referrer.
* @param referrerPubId The publication ID of the referrer, if any. Zero if no referrer.
* @param collectModuleData The data passed to the collect module's collect action. This is ABI-encoded and depends
* on the collect module chosen.
* @param timestamp The current block timestamp.
*/
event CollectedLegacy(
uint256 indexed publicationCollectedProfileId,
uint256 indexed publicationCollectedId,
address transactionExecutor,
uint256 referrerProfileId,
uint256 referrerPubId,
bytes collectModuleData,
uint256 timestamp
);
function collect(
Types.CollectParams calldata collectParams,
address transactionExecutor,
address collectorProfileOwner,
address collectNFTImpl
) external returns (uint256) {
ValidationLib.validateNotBlocked({
profile: collectParams.collectorProfileId,
byProfile: collectParams.publicationCollectedProfileId
});
address collectModule;
uint256 tokenId;
address collectNFT;
{
Types.Publication storage _collectedPublication = StorageLib.getPublication(
collectParams.publicationCollectedProfileId,
collectParams.publicationCollectedId
);
// This is a legacy collect operation, so we get the collect module from the deprecated storage field.
collectModule = _collectedPublication.__DEPRECATED__collectModule;
if (collectModule == address(0)) {
// It doesn't have collect module, thus it cannot be collected (a mirror or non-existent).
revert Errors.CollectNotAllowed();
}
if (collectParams.referrerProfileId != 0 || collectParams.referrerPubId != 0) {
ValidationLib.validateLegacyCollectReferrer(
collectParams.referrerProfileId,
collectParams.referrerPubId,
collectParams.publicationCollectedProfileId,
collectParams.publicationCollectedId
);
}
collectNFT = _getOrDeployCollectNFT(
_collectedPublication,
collectParams.publicationCollectedProfileId,
collectParams.publicationCollectedId,
collectNFTImpl
);
tokenId = ICollectNFT(collectNFT).mint(collectorProfileOwner);
}
ILegacyCollectModule(collectModule).processCollect({
// Legacy collect modules expect referrer profile ID to match the collected pub's author if no referrer set.
referrerProfileId: collectParams.referrerProfileId == 0
? collectParams.publicationCollectedProfileId
: collectParams.referrerProfileId,
// Collect NFT is minted to the `collectorProfileOwner`. Some follow-based constraints are expected to be
// broken in legacy collect modules if the `transactionExecutor` does not match the `collectorProfileOwner`.
collector: transactionExecutor,
profileId: collectParams.publicationCollectedProfileId,
pubId: collectParams.publicationCollectedId,
data: collectParams.collectModuleData
});
emit CollectedLegacy({
publicationCollectedProfileId: collectParams.publicationCollectedProfileId,
publicationCollectedId: collectParams.publicationCollectedId,
transactionExecutor: transactionExecutor,
referrerProfileId: collectParams.referrerProfileId,
referrerPubId: collectParams.referrerPubId,
collectModuleData: collectParams.collectModuleData,
timestamp: block.timestamp
});
return tokenId;
}
function _getOrDeployCollectNFT(
Types.Publication storage _collectedPublication,
uint256 publicationCollectedProfileId,
uint256 publicationCollectedId,
address collectNFTImpl
) private returns (address) {
address collectNFT = _collectedPublication.__DEPRECATED__collectNFT;
if (collectNFT == address(0)) {
collectNFT = _deployCollectNFT(publicationCollectedProfileId, publicationCollectedId, collectNFTImpl);
_collectedPublication.__DEPRECATED__collectNFT = collectNFT;
}
return collectNFT;
}
/**
* @notice Deploys the given profile's Collect NFT contract.
*
* @param profileId The token ID of the profile which Collect NFT should be deployed.
* @param pubId The publication ID of the publication being collected, which Collect NFT should be deployed.
* @param collectNFTImpl The address of the Collect NFT implementation that should be used for the deployment.
*
* @return address The address of the deployed Collect NFT contract.
*/
function _deployCollectNFT(uint256 profileId, uint256 pubId, address collectNFTImpl) private returns (address) {
address collectNFT = Clones.clone(collectNFTImpl);
string memory collectNFTName = string(
abi.encodePacked(profileId.toString(), COLLECT_NFT_NAME_INFIX, pubId.toString())
);
string memory collectNFTSymbol = string(
abi.encodePacked(profileId.toString(), COLLECT_NFT_SYMBOL_INFIX, pubId.toString())
);
ICollectNFT(collectNFT).initialize(profileId, pubId, collectNFTName, collectNFTSymbol);
emit Events.CollectNFTDeployed(profileId, pubId, collectNFT, block.timestamp);
return collectNFT;
}
}

View File

@@ -398,7 +398,7 @@ library MetaTxLib {
);
}
function validateCollectSignature(
function validateLegacyCollectSignature(
Types.EIP712Signature calldata signature,
Types.CollectParams calldata collectParams
) external {
@@ -406,12 +406,12 @@ library MetaTxLib {
_calculateDigest(
keccak256(
abi.encode(
Typehash.COLLECT,
Typehash.LEGACY_COLLECT,
collectParams.publicationCollectedProfileId,
collectParams.publicationCollectedId,
collectParams.collectorProfileId,
collectParams.referrerProfileIds,
collectParams.referrerPubIds,
collectParams.referrerProfileId,
collectParams.referrerPubId,
keccak256(collectParams.collectModuleData),
_getAndIncrementNonce(signature.signer),
signature.deadline

View File

@@ -259,7 +259,7 @@ library PublicationLib {
}
function _fillReferencePublicationStorage(
Types.ReferencePubParams memory referencePubParams,
Types.ReferencePubParams calldata referencePubParams,
Types.PublicationType referencePubType
) private returns (uint256) {
uint256 pubIdAssigned = ++StorageLib.getProfile(referencePubParams.profileId).pubCount;
@@ -273,14 +273,20 @@ library PublicationLib {
referencePubParams.pointedProfileId,
referencePubParams.pointedPubId
);
if (_pubPointed.pubType == Types.PublicationType.Post) {
Types.PublicationType pubPointedType = _pubPointed.pubType;
if (pubPointedType == Types.PublicationType.Post) {
// The publication pointed is a Lens V2 post.
_referencePub.rootProfileId = referencePubParams.pointedProfileId;
_referencePub.rootPubId = referencePubParams.pointedPubId;
} else {
// The publication pointed is either a comment or a quote.
} else if (pubPointedType == Types.PublicationType.Comment || pubPointedType == Types.PublicationType.Quote) {
// The publication pointed is either a Lens V2 comment or a Lens V2 quote.
// Note that even when the publication pointed is a V2 one, it will lack `rootProfileId` and `rootPubId` if
// there is a Lens V1 Legacy publication in the thread of interactions (including the root post itself).
_referencePub.rootProfileId = _pubPointed.rootProfileId;
_referencePub.rootPubId = _pubPointed.rootPubId;
}
// Otherwise the root is not filled, as the pointed publication is a Lens V1 Legacy publication, which does not
// support Lens V2 referral system.
return pubIdAssigned;
}

View File

@@ -87,8 +87,8 @@ library ValidationLib {
function validateReferrersAndGetReferrersPubTypes(
uint256[] memory referrerProfileIds,
uint256[] memory referrerPubIds,
uint256 profileId,
uint256 pubId
uint256 targetedProfileId,
uint256 targetedPubId
) internal view returns (Types.PublicationType[] memory) {
if (referrerProfileIds.length != referrerPubIds.length) {
revert Errors.ArrayMismatch();
@@ -105,8 +105,8 @@ library ValidationLib {
referrerPubTypes[i] = _validateReferrerAndGetReferrerPubType(
referrerProfileId,
referrerPubId,
profileId,
pubId
targetedProfileId,
targetedPubId
);
unchecked {
i++;
@@ -115,15 +115,34 @@ library ValidationLib {
return referrerPubTypes;
}
function validateLegacyCollectReferrer(
uint256 referrerProfileId,
uint256 referrerPubId,
uint256 publicationCollectedProfileId,
uint256 publicationCollectedId
) external view {
if (PublicationLib.getPublicationType(referrerProfileId, referrerPubId) != Types.PublicationType.Mirror) {
revert Errors.InvalidReferrer();
}
_validateReferrerAsMirror(
referrerProfileId,
referrerPubId,
publicationCollectedProfileId,
publicationCollectedId
);
}
function _validateReferrerAndGetReferrerPubType(
uint256 referrerProfileId,
uint256 referrerPubId,
uint256 profileId,
uint256 pubId
uint256 targetedProfileId,
uint256 targetedPubId
) private view returns (Types.PublicationType) {
if (referrerPubId == 0) {
// Unchecked/Unverified referral. Profile referrer, not attached to a publication.
if (StorageLib.getTokenData(referrerProfileId).owner == address(0) || referrerProfileId == profileId) {
if (
StorageLib.getTokenData(referrerProfileId).owner == address(0) || referrerProfileId == targetedProfileId
) {
revert Errors.InvalidReferrer();
}
return Types.PublicationType.Nonexistent;
@@ -131,19 +150,19 @@ library ValidationLib {
// Checked/Verified referral. Publication referrer.
if (
// Cannot pass itself as a referrer.
referrerProfileId == profileId && referrerPubId == pubId
referrerProfileId == targetedProfileId && referrerPubId == targetedPubId
) {
revert Errors.InvalidReferrer();
}
Types.PublicationType referrerPubType = PublicationLib.getPublicationType(referrerProfileId, referrerPubId);
if (referrerPubType == Types.PublicationType.Mirror) {
_validateReferrerAsMirror(referrerProfileId, referrerPubId, profileId, pubId);
_validateReferrerAsMirror(referrerProfileId, referrerPubId, targetedProfileId, targetedPubId);
} else if (
referrerPubType == Types.PublicationType.Comment || referrerPubType == Types.PublicationType.Quote
) {
_validateReferrerAsCommentOrQuote(referrerProfileId, referrerPubId, profileId, pubId);
_validateReferrerAsCommentOrQuote(referrerProfileId, referrerPubId, targetedProfileId, targetedPubId);
} else if (referrerPubType == Types.PublicationType.Post) {
_validateReferrerAsPost(referrerProfileId, referrerPubId, profileId, pubId);
_validateReferrerAsPost(referrerProfileId, referrerPubId, targetedProfileId, targetedPubId);
} else {
revert Errors.InvalidReferrer();
}
@@ -154,16 +173,13 @@ library ValidationLib {
function _validateReferrerAsPost(
uint256 referrerProfileId,
uint256 referrerPubId,
uint256 profileId,
uint256 pubId
uint256 targetedProfileId,
uint256 targetedPubId
) private view {
Types.Publication storage _publication = StorageLib.getPublication(profileId, pubId);
if (
// Publication being collected/referenced is not pointing to the referrer post and...
(_publication.pointedProfileId != referrerProfileId || _publication.pointedPubId != referrerPubId) &&
// ...publication being collected/referenced does not have the referrer post as the root.
(_publication.rootProfileId != referrerProfileId || _publication.rootPubId != referrerPubId)
) {
Types.Publication storage _targetedPub = StorageLib.getPublication(targetedProfileId, targetedPubId);
// Publication targeted must have the referrer post as the root. This enables the use case of rewarding the
// root publication for an action over any of its descendants.
if (_targetedPub.rootProfileId != referrerProfileId || _targetedPub.rootPubId != referrerPubId) {
revert Errors.InvalidReferrer();
}
}
@@ -171,13 +187,13 @@ library ValidationLib {
function _validateReferrerAsMirror(
uint256 referrerProfileId,
uint256 referrerPubId,
uint256 profileId,
uint256 pubId
uint256 targetedProfileId,
uint256 targetedPubId
) private view {
Types.Publication storage _referrerMirror = StorageLib.getPublication(referrerProfileId, referrerPubId);
if (
// A mirror can only be a referrer of a publication if it is pointing to it.
_referrerMirror.pointedProfileId != profileId || _referrerMirror.pointedPubId != pubId
_referrerMirror.pointedProfileId != targetedProfileId || _referrerMirror.pointedPubId != targetedPubId
) {
revert Errors.InvalidReferrer();
}
@@ -188,30 +204,35 @@ library ValidationLib {
*
* @param referrerProfileId The profile id of the referrer.
* @param referrerPubId The publication id of the referrer.
* @param profileId This is the ID of the profile who authored the publication being collected or referenced.
* @param pubId This is the pub user collects or references.
* @param targetedProfileId The ID of the profile who authored the publication being acted or referenced.
* @param targetedPubId The pub ID being acted or referenced.
*/
function _validateReferrerAsCommentOrQuote(
uint256 referrerProfileId,
uint256 referrerPubId,
uint256 profileId,
uint256 pubId
uint256 targetedProfileId,
uint256 targetedPubId
) private view {
Types.Publication storage _referrerPub = StorageLib.getPublication(referrerProfileId, referrerPubId);
Types.PublicationType typeOfPubPointedByReferrer = PublicationLib.getPublicationType(profileId, pubId);
// We already know that the publication being collected/referenced is not a mirror nor a non-existent one.
if (typeOfPubPointedByReferrer == Types.PublicationType.Post) {
// If the publication collected/referenced is a post, the referrer comment/quote must have it as the root.
if (_referrerPub.rootProfileId != profileId || _referrerPub.rootPubId != pubId) {
Types.PublicationType typeOfTargetedPub = PublicationLib.getPublicationType(targetedProfileId, targetedPubId);
// We already know that the publication being acted/referenced is not a mirror nor a non-existent one.
if (typeOfTargetedPub == Types.PublicationType.Post) {
// If the publication acted/referenced is a post, the referrer comment/quote must have it as the root.
if (_referrerPub.rootProfileId != targetedProfileId || _referrerPub.rootPubId != targetedPubId) {
revert Errors.InvalidReferrer();
}
} else {
// The publication collected/referenced is a comment or a quote.
Types.Publication storage _pubPointedByReferrer = StorageLib.getPublication(profileId, pubId);
// The referrer publication and the collected/referenced publication must share the same root.
// The publication acted/referenced is a comment or a quote.
Types.Publication storage _targetedPub = StorageLib.getPublication(targetedProfileId, targetedPubId);
if (
_referrerPub.rootProfileId != _pubPointedByReferrer.rootProfileId ||
_referrerPub.rootPubId != _pubPointedByReferrer.rootPubId
// Targeted pub must be a "pure" Lens V2 comment/quote, which means there is no Lens V1 Legacy comment
// or post on its tree of interactions, and its root pub is filled.
// Otherwise, two Lens V2 "non-pure" publications could be passed as a referrer to each other,
// even without having any interaction in common.
_targetedPub.rootPubId == 0 ||
// The referrer publication and the acted/referenced publication must share the same root.
_referrerPub.rootProfileId != _targetedPub.rootProfileId ||
_referrerPub.rootPubId != _targetedPub.rootPubId
) {
revert Errors.InvalidReferrer();
}

View File

@@ -27,7 +27,6 @@ library Errors {
error NotFollowing();
error SelfFollow();
error InvalidReferrer();
error DeprecaredModulesOnlySupportOneReferrer();
error InvalidPointedPub();
error NonERC721ReceiverImplementer();
@@ -38,7 +37,7 @@ library Errors {
error InitParamsInvalid();
error ActionNotAllowed();
error CollectNotAllowed(); // Used in CollectLib (pending deprecation)
error CollectNotAllowed(); // Used in LegacyCollectLib (pending deprecation)
// MultiState Errors
error Paused();

View File

@@ -10,7 +10,7 @@ library Typehash {
bytes32 constant CHANGE_DELEGATED_EXECUTORS_CONFIG = keccak256('ChangeDelegatedExecutorsConfig(uint256 delegatorProfileId,address[] delegatedExecutors,bool[] approvals,uint64 configNumber,bool switchToGivenConfig,uint256 nonce,uint256 deadline)');
bytes32 constant COLLECT = keccak256('Collect(uint256 publicationCollectedProfileId,uint256 publicationCollectedId,uint256 collectorProfileId,uint256[] referrerProfileIds,uint256[] referrerPubIds,bytes collectModuleData,uint256 nonce,uint256 deadline)');
bytes32 constant LEGACY_COLLECT = keccak256('Collect(uint256 publicationCollectedProfileId,uint256 publicationCollectedId,uint256 collectorProfileId,uint256 referrerProfileId,uint256 referrerPubId,bytes collectModuleData,uint256 nonce,uint256 deadline)');
bytes32 constant COMMENT = keccak256('Comment(uint256 profileId,string contentURI,uint256 pointedProfileId,uint256 pointedPubId,uint256[] referrerProfileIds,uint256[] referrerPubIds,bytes referenceModuleData,address collectModule,bytes collectModuleInitData,address referenceModule,bytes referenceModuleInitData,uint256 nonce,uint256 deadline)');

View File

@@ -261,21 +261,22 @@ library Types {
/**
* Deprecated in V2: Will be removed after some time after upgrading to V2.
* @notice A struct containing the parameters required for the `collect()` function.
* @notice A struct containing the parameters required for the legacy `collect()` function.
* @dev The referrer can only be a mirror of the publication being collected.
*
* @param publicationCollectedProfileId The token ID of the profile that published the publication to collect.
* @param publicationCollectedId The publication to collect's publication ID.
* @param collectorProfileId The collector profile.
* @param referrerProfileId
* @param referrerPubId
* @param referrerProfileId The ID of a profile that authored a mirror that helped discovering the collected pub.
* @param referrerPubId The ID of the mirror that helped discovering the collected pub.
* @param collectModuleData The arbitrary data to pass to the collectModule if needed.
*/
struct CollectParams {
uint256 publicationCollectedProfileId;
uint256 publicationCollectedId;
uint256 collectorProfileId;
uint256[] referrerProfileIds;
uint256[] referrerPubIds;
uint256 referrerProfileId;
uint256 referrerPubId;
bytes collectModuleData;
}

View File

@@ -6,7 +6,7 @@ test = 'test/foundry'
cache_path = 'forge-cache'
fs_permissions = [{ access = "read-write", path = "./"}]
optimizer = true
optimizer_runs = 65
optimizer_runs = 10
ignored_error_codes = []
[rpc_endpoints]

View File

@@ -311,8 +311,8 @@ contract UpgradeForkTest is BaseTest {
publicationCollectedProfileId: profileId,
publicationCollectedId: 1,
collectorProfileId: profileId,
referrerProfileIds: _emptyUint256Array(),
referrerPubIds: _emptyUint256Array(),
referrerProfileId: 0,
referrerPubId: 0,
collectModuleData: ''
})
);
@@ -321,8 +321,8 @@ contract UpgradeForkTest is BaseTest {
publicationCollectedProfileId: profileId,
publicationCollectedId: 2,
collectorProfileId: profileId,
referrerProfileIds: _emptyUint256Array(),
referrerPubIds: _emptyUint256Array(),
referrerProfileId: 0,
referrerPubId: 0,
collectModuleData: ''
})
);
@@ -331,8 +331,8 @@ contract UpgradeForkTest is BaseTest {
publicationCollectedProfileId: profileId,
publicationCollectedId: 3,
collectorProfileId: profileId,
referrerProfileIds: _emptyUint256Array(),
referrerPubIds: _emptyUint256Array(),
referrerProfileId: 0,
referrerPubId: 0,
collectModuleData: ''
})
);