From 20139fd5f510b0ef4ff1fd24aa9ad1a2d907dfd0 Mon Sep 17 00:00:00 2001 From: Alan Donoso Naumczuk Date: Tue, 7 Jan 2025 17:31:35 -0300 Subject: [PATCH 01/41] misc: TODO solved - isImmutable storage replaced by _contentURISnapshot length check --- contracts/actions/post/collect/LensCollectedPost.sol | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/contracts/actions/post/collect/LensCollectedPost.sol b/contracts/actions/post/collect/LensCollectedPost.sol index b3895fcd..26052c40 100644 --- a/contracts/actions/post/collect/LensCollectedPost.sol +++ b/contracts/actions/post/collect/LensCollectedPost.sol @@ -24,7 +24,6 @@ contract LensCollectedPost is LensERC721, IERC7572 { string internal _contractURI; address internal immutable _feed; uint256 internal immutable _postId; - bool internal immutable _isImmutable; // TODO: This can be replaced with bytes(_contentURISnapshot).length address internal immutable _collectAction; constructor(address feed, uint256 postId, bool isImmutable) { @@ -33,7 +32,6 @@ contract LensCollectedPost is LensERC721, IERC7572 { require(bytes(contentURI).length > 0, "Post content URI is empty"); _feed = feed; _postId = postId; - _isImmutable = isImmutable; _contractURI = contentURI; _collectAction = msg.sender; if (isImmutable) { @@ -54,7 +52,7 @@ contract LensCollectedPost is LensERC721, IERC7572 { } function tokenURI(uint256 /*tokenId*/ ) public view override returns (string memory) { - if (_isImmutable) { + if (bytes(_contentURISnapshot).length > 0) { return _contentURISnapshot; } else { string memory contentURI = IFeed(_feed).getPost(_postId).contentURI; From 8eab9527bbef58ad392447627774ac3ea0b31c3f Mon Sep 17 00:00:00 2001 From: Alan Donoso Naumczuk Date: Thu, 9 Jan 2025 13:52:13 -0300 Subject: [PATCH 02/41] fix: Missing rule selector validation on primitives added --- contracts/core/base/RuleBasedPrimitive.sol | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/contracts/core/base/RuleBasedPrimitive.sol b/contracts/core/base/RuleBasedPrimitive.sol index 4b6840ed..40b8eb6b 100644 --- a/contracts/core/base/RuleBasedPrimitive.sol +++ b/contracts/core/base/RuleBasedPrimitive.sol @@ -165,6 +165,10 @@ abstract contract RuleBasedPrimitive { ); } for (uint256 j = 0; j < ruleChange.selectorChanges.length; j++) { + _validateIsSupportedRuleSelector( + ruleChange.selectorChanges[j].ruleSelector, + entityId == 0 ? _supportedPrimitiveRuleSelectors() : _supportedEntityRuleSelectors() + ); rulesStorage._changeRulesSelectors( ruleChanges[i].ruleAddress, ruleChange.configSalt, @@ -190,6 +194,18 @@ abstract contract RuleBasedPrimitive { return new bytes4[](0); } + function _validateIsSupportedRuleSelector(bytes4 ruleSelectorToValidate, bytes4[] memory supportedRuleSelectors) + internal + pure + { + for (uint256 i = 0; i < supportedRuleSelectors.length; i++) { + if (ruleSelectorToValidate == supportedRuleSelectors[i]) { + return; + } + } + revert(); + } + function _beforeChangeRules(uint256 entityId, RuleChange[] calldata ruleChanges) internal virtual { if (entityId == 0) { _beforeChangePrimitiveRules(ruleChanges); From 6f7274f082fa5d31950b563fcb0d4198dbcf1205 Mon Sep 17 00:00:00 2001 From: Alan Donoso Naumczuk Date: Thu, 9 Jan 2025 15:23:33 -0300 Subject: [PATCH 03/41] misc: compiler bump to 0.8.28 - pragma bump to ^0.8.26 - preparing for custom errors --- contracts/actions/account/TippingAccountAction.sol | 2 +- contracts/actions/account/base/BaseAccountAction.sol | 2 +- contracts/actions/base/BaseAction.sol | 2 +- contracts/actions/post/TippingPostAction.sol | 2 +- contracts/actions/post/base/BasePostAction.sol | 2 +- contracts/actions/post/collect/IERC7572.sol | 2 +- contracts/actions/post/collect/ISimpleCollectAction.sol | 2 +- contracts/actions/post/collect/LensCollectedPost.sol | 2 +- contracts/actions/post/collect/SimpleCollectAction.sol | 2 +- contracts/core/access/AccessControlled.sol | 2 +- contracts/core/access/Ownable.sol | 2 +- contracts/core/access/RoleBasedAccessControl.sol | 2 +- contracts/core/base/BaseSource.sol | 2 +- contracts/core/base/ExtraStorageBased.sol | 2 +- contracts/core/base/LensERC721.sol | 2 +- contracts/core/base/MetadataBased.sol | 2 +- contracts/core/base/RuleBasedPrimitive.sol | 2 +- contracts/core/base/SourceStampBased.sol | 2 +- contracts/core/interfaces/IAccessControl.sol | 2 +- contracts/core/interfaces/IERC4906Events.sol | 2 +- contracts/core/interfaces/IERC721.sol | 2 +- contracts/core/interfaces/IFeed.sol | 2 +- contracts/core/interfaces/IFeedRule.sol | 2 +- contracts/core/interfaces/IFollowRule.sol | 2 +- contracts/core/interfaces/IGraph.sol | 2 +- contracts/core/interfaces/IGraphRule.sol | 2 +- contracts/core/interfaces/IGroup.sol | 2 +- contracts/core/interfaces/IGroupRule.sol | 2 +- contracts/core/interfaces/ILock.sol | 2 +- contracts/core/interfaces/IMetadataBased.sol | 2 +- contracts/core/interfaces/INamespace.sol | 2 +- contracts/core/interfaces/INamespaceRule.sol | 2 +- contracts/core/interfaces/IPostRule.sol | 2 +- contracts/core/interfaces/IRoleBasedAccessControl.sol | 2 +- contracts/core/interfaces/ISource.sol | 2 +- contracts/core/interfaces/ITokenURIProvider.sol | 2 +- contracts/core/interfaces/IVersionedBeacon.sol | 2 +- contracts/core/libraries/AccessControlLib.sol | 2 +- contracts/core/libraries/CallLib.sol | 2 +- contracts/core/libraries/EIP712EncodingLib.sol | 2 +- contracts/core/libraries/ExtraDataLib.sol | 2 +- contracts/core/libraries/RulesLib.sol | 2 +- contracts/core/primitives/feed/Feed.sol | 2 +- contracts/core/primitives/feed/FeedCore.sol | 2 +- contracts/core/primitives/feed/RuleBasedFeed.sol | 2 +- contracts/core/primitives/graph/Graph.sol | 2 +- contracts/core/primitives/graph/GraphCore.sol | 2 +- contracts/core/primitives/graph/RuleBasedGraph.sol | 2 +- contracts/core/primitives/group/Group.sol | 2 +- contracts/core/primitives/group/GroupCore.sol | 2 +- contracts/core/primitives/group/RuleBasedGroup.sol | 2 +- .../primitives/namespace/LensUsernameTokenURIProvider.sol | 2 +- contracts/core/primitives/namespace/Namespace.sol | 6 +++--- contracts/core/primitives/namespace/NamespaceCore.sol | 2 +- contracts/core/primitives/namespace/RuleBasedNamespace.sol | 2 +- contracts/core/types/Events.sol | 2 +- contracts/core/types/Types.sol | 2 +- contracts/core/upgradeability/Beacon.sol | 2 +- contracts/core/upgradeability/BeaconProxy.sol | 2 +- contracts/core/upgradeability/Initializable.sol | 2 +- contracts/core/upgradeability/Lock.sol | 2 +- contracts/core/upgradeability/ProxyAdmin.sol | 2 +- contracts/extensions/access/OwnerAdminOnlyAccessControl.sol | 2 +- contracts/extensions/access/PermissionlessAccessControl.sol | 2 +- contracts/extensions/account/Account.sol | 2 +- contracts/extensions/account/IAccount.sol | 2 +- contracts/extensions/actions/ActionHub.sol | 2 +- contracts/extensions/factories/AccessControlFactory.sol | 2 +- contracts/extensions/factories/AccountFactory.sol | 2 +- contracts/extensions/factories/AppFactory.sol | 2 +- contracts/extensions/factories/FeedFactory.sol | 2 +- contracts/extensions/factories/GraphFactory.sol | 2 +- contracts/extensions/factories/GroupFactory.sol | 2 +- contracts/extensions/factories/LensFactory.sol | 2 +- contracts/extensions/factories/NamespaceFactory.sol | 2 +- contracts/extensions/factories/PrimitiveFactory.sol | 2 +- contracts/extensions/primitives/app/App.sol | 2 +- contracts/extensions/primitives/app/AppCore.sol | 2 +- contracts/extensions/primitives/app/IApp.sol | 2 +- .../extensions/registries/CurrencyRegistry_MockEvents.sol | 2 +- .../registries/PostActionsRegistry_MockEvents.sol | 2 +- contracts/migration/MigrationFeed.sol | 2 +- contracts/migration/MigrationGraph.sol | 2 +- contracts/rules/base/AccountBlockingRule.sol | 2 +- contracts/rules/base/RestrictedSignersRule.sol | 2 +- contracts/rules/base/SimplePaymentRule.sol | 2 +- contracts/rules/base/TokenGatedRule.sol | 2 +- contracts/rules/feed/GroupGatedFeedRule.sol | 2 +- contracts/rules/feed/RestrictedSignersFeedRule.sol | 2 +- contracts/rules/feed/SimplePaymentFeedRule.sol | 2 +- contracts/rules/feed/TokenGatedFeedRule.sol | 2 +- contracts/rules/follow/SimplePaymentFollowRule.sol | 2 +- contracts/rules/follow/TokenGatedFollowRule.sol | 2 +- contracts/rules/graph/GroupGatedGraphRule.sol | 2 +- contracts/rules/graph/RestrictedSignersGraphRule.sol | 2 +- contracts/rules/graph/TokenGatedGraphRule.sol | 2 +- contracts/rules/group/BanMemberGroupRule.sol | 2 +- contracts/rules/group/MembershipApprovalGroupRule.sol | 2 +- contracts/rules/group/SimplePaymentGroupRule.sol | 2 +- contracts/rules/group/TokenGatedGroupRule.sol | 2 +- contracts/rules/namespace/SimplePaymentNamespaceRule.sol | 2 +- contracts/rules/namespace/TokenGatedNamespaceRule.sol | 2 +- contracts/rules/namespace/UsernameCharsetNamespaceRule.sol | 2 +- contracts/rules/namespace/UsernameLengthNamespaceRule.sol | 2 +- contracts/rules/namespace/UsernameReservedNamespaceRule.sol | 2 +- contracts/rules/post/FollowersOnlyPostRule.sol | 2 +- foundry.toml | 2 +- hardhat.config.ts | 2 +- test/Account.t.sol | 2 +- test/access-control/OwnerAdminOnlyAccessControl.t.sol | 2 +- test/app/App.t.sol | 2 +- test/factories/LensFactory.t.sol | 2 +- test/helpers/BaseDeployments.sol | 2 +- test/helpers/TypeHelpers.sol | 2 +- test/primitives/Feed.t.sol | 2 +- test/primitives/Graph.t.sol | 2 +- test/primitives/Group.t.sol | 2 +- test/primitives/Namespace.t.sol | 2 +- 118 files changed, 120 insertions(+), 120 deletions(-) diff --git a/contracts/actions/account/TippingAccountAction.sol b/contracts/actions/account/TippingAccountAction.sol index 253732d8..aa25729b 100644 --- a/contracts/actions/account/TippingAccountAction.sol +++ b/contracts/actions/account/TippingAccountAction.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {BaseAccountAction} from "contracts/actions/account/base/BaseAccountAction.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; diff --git a/contracts/actions/account/base/BaseAccountAction.sol b/contracts/actions/account/base/BaseAccountAction.sol index 6a179e78..9aab041d 100644 --- a/contracts/actions/account/base/BaseAccountAction.sol +++ b/contracts/actions/account/base/BaseAccountAction.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {KeyValue} from "contracts/core/types/Types.sol"; import {BaseAction} from "contracts/actions/base/BaseAction.sol"; diff --git a/contracts/actions/base/BaseAction.sol b/contracts/actions/base/BaseAction.sol index fe7b91bc..b9310448 100644 --- a/contracts/actions/base/BaseAction.sol +++ b/contracts/actions/base/BaseAction.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {UNIVERSAL_ACTION_MAGIC_VALUE} from "contracts/extensions/actions/ActionHub.sol"; diff --git a/contracts/actions/post/TippingPostAction.sol b/contracts/actions/post/TippingPostAction.sol index 8cfba0b9..0977e03a 100644 --- a/contracts/actions/post/TippingPostAction.sol +++ b/contracts/actions/post/TippingPostAction.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {BasePostAction} from "contracts/actions/post/base/BasePostAction.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; diff --git a/contracts/actions/post/base/BasePostAction.sol b/contracts/actions/post/base/BasePostAction.sol index 2dc1bcfb..c8178c14 100644 --- a/contracts/actions/post/base/BasePostAction.sol +++ b/contracts/actions/post/base/BasePostAction.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {KeyValue} from "contracts/core/types/Types.sol"; import {BaseAction} from "contracts/actions/base/BaseAction.sol"; diff --git a/contracts/actions/post/collect/IERC7572.sol b/contracts/actions/post/collect/IERC7572.sol index efb9d714..0c148614 100644 --- a/contracts/actions/post/collect/IERC7572.sol +++ b/contracts/actions/post/collect/IERC7572.sol @@ -2,7 +2,7 @@ // Copyright (C) 2024 Lens Labs. All Rights Reserved. // As appears in https://eips.ethereum.org/EIPS/eip-7572 -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; /** * This specification standardizes contractURI() to return contract-level metadata. This is useful for dapps and diff --git a/contracts/actions/post/collect/ISimpleCollectAction.sol b/contracts/actions/post/collect/ISimpleCollectAction.sol index 2d812d0a..6967c968 100644 --- a/contracts/actions/post/collect/ISimpleCollectAction.sol +++ b/contracts/actions/post/collect/ISimpleCollectAction.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IPostAction} from "contracts/extensions/actions/ActionHub.sol"; diff --git a/contracts/actions/post/collect/LensCollectedPost.sol b/contracts/actions/post/collect/LensCollectedPost.sol index 26052c40..8f82168f 100644 --- a/contracts/actions/post/collect/LensCollectedPost.sol +++ b/contracts/actions/post/collect/LensCollectedPost.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import "contracts/core/base/LensERC721.sol"; import {IERC7572} from "contracts/actions/post/collect/IERC7572.sol"; diff --git a/contracts/actions/post/collect/SimpleCollectAction.sol b/contracts/actions/post/collect/SimpleCollectAction.sol index 441f6986..f1a84551 100644 --- a/contracts/actions/post/collect/SimpleCollectAction.sol +++ b/contracts/actions/post/collect/SimpleCollectAction.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {ISimpleCollectAction, CollectActionData} from "contracts/actions/post/collect/ISimpleCollectAction.sol"; import {IFeed} from "contracts/core/interfaces/IFeed.sol"; diff --git a/contracts/core/access/AccessControlled.sol b/contracts/core/access/AccessControlled.sol index d25ee3a1..13bee0c2 100644 --- a/contracts/core/access/AccessControlled.sol +++ b/contracts/core/access/AccessControlled.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IAccessControl} from "contracts/core/interfaces/IAccessControl.sol"; import {AccessControlLib} from "contracts/core/libraries/AccessControlLib.sol"; diff --git a/contracts/core/access/Ownable.sol b/contracts/core/access/Ownable.sol index 60441bfd..d09e3418 100644 --- a/contracts/core/access/Ownable.sol +++ b/contracts/core/access/Ownable.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.12; +pragma solidity ^0.8.26; abstract contract Ownable { event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); diff --git a/contracts/core/access/RoleBasedAccessControl.sol b/contracts/core/access/RoleBasedAccessControl.sol index c6f72ce7..dfa5ef75 100644 --- a/contracts/core/access/RoleBasedAccessControl.sol +++ b/contracts/core/access/RoleBasedAccessControl.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {Access, IRoleBasedAccessControl} from "contracts/core/interfaces/IRoleBasedAccessControl.sol"; import {Events} from "contracts/core/types/Events.sol"; diff --git a/contracts/core/base/BaseSource.sol b/contracts/core/base/BaseSource.sol index 2e9a7f3f..84e398a8 100644 --- a/contracts/core/base/BaseSource.sol +++ b/contracts/core/base/BaseSource.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {ISource} from "contracts/core/interfaces/ISource.sol"; import {SourceStamp} from "contracts/core/types/Types.sol"; diff --git a/contracts/core/base/ExtraStorageBased.sol b/contracts/core/base/ExtraStorageBased.sol index 355c0e14..0754e930 100644 --- a/contracts/core/base/ExtraStorageBased.sol +++ b/contracts/core/base/ExtraStorageBased.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {KeyValue} from "contracts/core/types/Types.sol"; import {ExtraDataLib} from "contracts/core/libraries/ExtraDataLib.sol"; diff --git a/contracts/core/base/LensERC721.sol b/contracts/core/base/LensERC721.sol index ee324d13..a337c180 100644 --- a/contracts/core/base/LensERC721.sol +++ b/contracts/core/base/LensERC721.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. // Modified from OpenZeppelin's v4.9.0 contracts -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import "contracts/core/interfaces/IERC721.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol"; diff --git a/contracts/core/base/MetadataBased.sol b/contracts/core/base/MetadataBased.sol index ccfc0ac2..523652fe 100644 --- a/contracts/core/base/MetadataBased.sol +++ b/contracts/core/base/MetadataBased.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.17; +pragma solidity ^0.8.26; import {IMetadataBased} from "contracts/core/interfaces/IMetadataBased.sol"; diff --git a/contracts/core/base/RuleBasedPrimitive.sol b/contracts/core/base/RuleBasedPrimitive.sol index 40b8eb6b..6a81fc55 100644 --- a/contracts/core/base/RuleBasedPrimitive.sol +++ b/contracts/core/base/RuleBasedPrimitive.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {RulesStorage, RulesLib} from "contracts/core/libraries/RulesLib.sol"; import { diff --git a/contracts/core/base/SourceStampBased.sol b/contracts/core/base/SourceStampBased.sol index 67042153..bd1b3069 100644 --- a/contracts/core/base/SourceStampBased.sol +++ b/contracts/core/base/SourceStampBased.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {KeyValue, SourceStamp} from "contracts/core/types/Types.sol"; import {ExtraStorageBased} from "contracts/core/base/ExtraStorageBased.sol"; diff --git a/contracts/core/interfaces/IAccessControl.sol b/contracts/core/interfaces/IAccessControl.sol index 9e2bf965..54bd1564 100644 --- a/contracts/core/interfaces/IAccessControl.sol +++ b/contracts/core/interfaces/IAccessControl.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; interface IAccessControl { /** diff --git a/contracts/core/interfaces/IERC4906Events.sol b/contracts/core/interfaces/IERC4906Events.sol index 65bf5d7d..1ab7dff8 100644 --- a/contracts/core/interfaces/IERC4906Events.sol +++ b/contracts/core/interfaces/IERC4906Events.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; library IERC4906Events { /// @dev This event emits when the metadata of a token is changed. diff --git a/contracts/core/interfaces/IERC721.sol b/contracts/core/interfaces/IERC721.sol index 5d0f27e2..ef74a788 100644 --- a/contracts/core/interfaces/IERC721.sol +++ b/contracts/core/interfaces/IERC721.sol @@ -2,7 +2,7 @@ // Copyright (C) 2024 Lens Labs. All Rights Reserved. // Modified from OpenZeppelin's v4.9.0 contracts -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; /** * @dev Required interface of an ERC721 compliant contract. diff --git a/contracts/core/interfaces/IFeed.sol b/contracts/core/interfaces/IFeed.sol index a18d0d6a..f5e4f36a 100644 --- a/contracts/core/interfaces/IFeed.sol +++ b/contracts/core/interfaces/IFeed.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {KeyValue, Rule, RuleProcessingParams, RuleChange} from "contracts/core/types/Types.sol"; import {IMetadataBased} from "contracts/core/interfaces/IMetadataBased.sol"; diff --git a/contracts/core/interfaces/IFeedRule.sol b/contracts/core/interfaces/IFeedRule.sol index e22125b3..1b082c0f 100644 --- a/contracts/core/interfaces/IFeedRule.sol +++ b/contracts/core/interfaces/IFeedRule.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {CreatePostParams, EditPostParams} from "contracts/core/interfaces/IFeed.sol"; import {KeyValue, RuleChange} from "contracts/core/types/Types.sol"; diff --git a/contracts/core/interfaces/IFollowRule.sol b/contracts/core/interfaces/IFollowRule.sol index 70c60c24..499d4583 100644 --- a/contracts/core/interfaces/IFollowRule.sol +++ b/contracts/core/interfaces/IFollowRule.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {KeyValue} from "contracts/core/types/Types.sol"; diff --git a/contracts/core/interfaces/IGraph.sol b/contracts/core/interfaces/IGraph.sol index 509509c4..51628a28 100644 --- a/contracts/core/interfaces/IGraph.sol +++ b/contracts/core/interfaces/IGraph.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {RuleProcessingParams, KeyValue, RuleChange, Rule} from "contracts/core/types/Types.sol"; import {IMetadataBased} from "contracts/core/interfaces/IMetadataBased.sol"; diff --git a/contracts/core/interfaces/IGraphRule.sol b/contracts/core/interfaces/IGraphRule.sol index dbdc7e03..432a69ef 100644 --- a/contracts/core/interfaces/IGraphRule.sol +++ b/contracts/core/interfaces/IGraphRule.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {KeyValue, RuleChange} from "contracts/core/types/Types.sol"; diff --git a/contracts/core/interfaces/IGroup.sol b/contracts/core/interfaces/IGroup.sol index 9a4641e4..9b6e90d3 100644 --- a/contracts/core/interfaces/IGroup.sol +++ b/contracts/core/interfaces/IGroup.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {KeyValue, RuleChange, RuleProcessingParams, Rule} from "contracts/core/types/Types.sol"; import {IMetadataBased} from "contracts/core/interfaces/IMetadataBased.sol"; diff --git a/contracts/core/interfaces/IGroupRule.sol b/contracts/core/interfaces/IGroupRule.sol index e8a41f98..7d54f393 100644 --- a/contracts/core/interfaces/IGroupRule.sol +++ b/contracts/core/interfaces/IGroupRule.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {KeyValue} from "contracts/core/types/Types.sol"; diff --git a/contracts/core/interfaces/ILock.sol b/contracts/core/interfaces/ILock.sol index f572f56c..12141fe6 100644 --- a/contracts/core/interfaces/ILock.sol +++ b/contracts/core/interfaces/ILock.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; interface ILock { /** diff --git a/contracts/core/interfaces/IMetadataBased.sol b/contracts/core/interfaces/IMetadataBased.sol index 786d098c..d1c7fa70 100644 --- a/contracts/core/interfaces/IMetadataBased.sol +++ b/contracts/core/interfaces/IMetadataBased.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; interface IMetadataBased { function getMetadataURI() external view returns (string memory); diff --git a/contracts/core/interfaces/INamespace.sol b/contracts/core/interfaces/INamespace.sol index 1b6e7453..31d9bbef 100644 --- a/contracts/core/interfaces/INamespace.sol +++ b/contracts/core/interfaces/INamespace.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {KeyValue, RuleChange, RuleProcessingParams, Rule} from "contracts/core/types/Types.sol"; import {IMetadataBased} from "contracts/core/interfaces/IMetadataBased.sol"; diff --git a/contracts/core/interfaces/INamespaceRule.sol b/contracts/core/interfaces/INamespaceRule.sol index 55dbd574..cef71656 100644 --- a/contracts/core/interfaces/INamespaceRule.sol +++ b/contracts/core/interfaces/INamespaceRule.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {KeyValue} from "contracts/core/types/Types.sol"; diff --git a/contracts/core/interfaces/IPostRule.sol b/contracts/core/interfaces/IPostRule.sol index 6b4433f3..d7bf9499 100644 --- a/contracts/core/interfaces/IPostRule.sol +++ b/contracts/core/interfaces/IPostRule.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {CreatePostParams, EditPostParams} from "contracts/core/interfaces/IFeed.sol"; import {KeyValue} from "contracts/core/types/Types.sol"; diff --git a/contracts/core/interfaces/IRoleBasedAccessControl.sol b/contracts/core/interfaces/IRoleBasedAccessControl.sol index 673bb092..4202fb80 100644 --- a/contracts/core/interfaces/IRoleBasedAccessControl.sol +++ b/contracts/core/interfaces/IRoleBasedAccessControl.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IAccessControl} from "contracts/core/interfaces/IAccessControl.sol"; diff --git a/contracts/core/interfaces/ISource.sol b/contracts/core/interfaces/ISource.sol index 750957fd..f78bbda5 100644 --- a/contracts/core/interfaces/ISource.sol +++ b/contracts/core/interfaces/ISource.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.17; +pragma solidity ^0.8.26; import {SourceStamp} from "contracts/core/types/Types.sol"; diff --git a/contracts/core/interfaces/ITokenURIProvider.sol b/contracts/core/interfaces/ITokenURIProvider.sol index 5571d9be..ebb77e7f 100644 --- a/contracts/core/interfaces/ITokenURIProvider.sol +++ b/contracts/core/interfaces/ITokenURIProvider.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; interface ITokenURIProvider { function tokenURI(uint256 tokenId) external view returns (string memory); diff --git a/contracts/core/interfaces/IVersionedBeacon.sol b/contracts/core/interfaces/IVersionedBeacon.sol index 8b8fe9cd..9643c331 100644 --- a/contracts/core/interfaces/IVersionedBeacon.sol +++ b/contracts/core/interfaces/IVersionedBeacon.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; interface IVersionedBeacon { /** diff --git a/contracts/core/libraries/AccessControlLib.sol b/contracts/core/libraries/AccessControlLib.sol index e34eb6dd..e204c52a 100644 --- a/contracts/core/libraries/AccessControlLib.sol +++ b/contracts/core/libraries/AccessControlLib.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.17; +pragma solidity ^0.8.26; import {IAccessControl} from "contracts/core/interfaces/IAccessControl.sol"; diff --git a/contracts/core/libraries/CallLib.sol b/contracts/core/libraries/CallLib.sol index 8d7df848..1b6b0e26 100644 --- a/contracts/core/libraries/CallLib.sol +++ b/contracts/core/libraries/CallLib.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.17; +pragma solidity ^0.8.26; library CallLib { function safecall(address target, bytes memory data) internal returns (bool, bytes memory) { diff --git a/contracts/core/libraries/EIP712EncodingLib.sol b/contracts/core/libraries/EIP712EncodingLib.sol index 3960b363..56f455a9 100644 --- a/contracts/core/libraries/EIP712EncodingLib.sol +++ b/contracts/core/libraries/EIP712EncodingLib.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.17; +pragma solidity ^0.8.26; import {KeyValue, RuleChange, RuleConfigurationChange, RuleSelectorChange} from "contracts/core/types/Types.sol"; import {CreatePostParams, EditPostParams} from "contracts/core/interfaces/IFeed.sol"; diff --git a/contracts/core/libraries/ExtraDataLib.sol b/contracts/core/libraries/ExtraDataLib.sol index 919ce9b7..629f8d40 100644 --- a/contracts/core/libraries/ExtraDataLib.sol +++ b/contracts/core/libraries/ExtraDataLib.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.17; +pragma solidity ^0.8.26; import {KeyValue} from "contracts/core/types/Types.sol"; diff --git a/contracts/core/libraries/RulesLib.sol b/contracts/core/libraries/RulesLib.sol index e6f96ec4..991ddcba 100644 --- a/contracts/core/libraries/RulesLib.sol +++ b/contracts/core/libraries/RulesLib.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {Rule} from "contracts/core/types/Types.sol"; import {CallLib} from "contracts/core/libraries/CallLib.sol"; diff --git a/contracts/core/primitives/feed/Feed.sol b/contracts/core/primitives/feed/Feed.sol index efe50d38..140501c3 100644 --- a/contracts/core/primitives/feed/Feed.sol +++ b/contracts/core/primitives/feed/Feed.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IFeed, Post, EditPostParams, CreatePostParams} from "contracts/core/interfaces/IFeed.sol"; import {FeedCore as Core} from "contracts/core/primitives/feed/FeedCore.sol"; diff --git a/contracts/core/primitives/feed/FeedCore.sol b/contracts/core/primitives/feed/FeedCore.sol index 57dbdb82..2e193320 100644 --- a/contracts/core/primitives/feed/FeedCore.sol +++ b/contracts/core/primitives/feed/FeedCore.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.17; +pragma solidity ^0.8.26; import {EditPostParams, CreatePostParams} from "contracts/core/interfaces/IFeed.sol"; diff --git a/contracts/core/primitives/feed/RuleBasedFeed.sol b/contracts/core/primitives/feed/RuleBasedFeed.sol index e54f1ad4..35a58b55 100644 --- a/contracts/core/primitives/feed/RuleBasedFeed.sol +++ b/contracts/core/primitives/feed/RuleBasedFeed.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IPostRule} from "contracts/core/interfaces/IPostRule.sol"; import {IFeedRule} from "contracts/core/interfaces/IFeedRule.sol"; diff --git a/contracts/core/primitives/graph/Graph.sol b/contracts/core/primitives/graph/Graph.sol index 7284b482..5ae74183 100644 --- a/contracts/core/primitives/graph/Graph.sol +++ b/contracts/core/primitives/graph/Graph.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {Follow, IGraph} from "contracts/core/interfaces/IGraph.sol"; import {GraphCore as Core} from "contracts/core/primitives/graph/GraphCore.sol"; diff --git a/contracts/core/primitives/graph/GraphCore.sol b/contracts/core/primitives/graph/GraphCore.sol index af3b9a44..6840f613 100644 --- a/contracts/core/primitives/graph/GraphCore.sol +++ b/contracts/core/primitives/graph/GraphCore.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.17; +pragma solidity ^0.8.26; import {Follow} from "contracts/core/interfaces/IGraph.sol"; diff --git a/contracts/core/primitives/graph/RuleBasedGraph.sol b/contracts/core/primitives/graph/RuleBasedGraph.sol index 7f7ae841..71838d92 100644 --- a/contracts/core/primitives/graph/RuleBasedGraph.sol +++ b/contracts/core/primitives/graph/RuleBasedGraph.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IFollowRule} from "contracts/core/interfaces/IFollowRule.sol"; import {IGraphRule} from "contracts/core/interfaces/IGraphRule.sol"; diff --git a/contracts/core/primitives/group/Group.sol b/contracts/core/primitives/group/Group.sol index 09222c1a..49ea88d7 100644 --- a/contracts/core/primitives/group/Group.sol +++ b/contracts/core/primitives/group/Group.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {Membership, IGroup} from "contracts/core/interfaces/IGroup.sol"; import {GroupCore as Core} from "contracts/core/primitives/group/GroupCore.sol"; diff --git a/contracts/core/primitives/group/GroupCore.sol b/contracts/core/primitives/group/GroupCore.sol index 3ac777e7..0fee6e0b 100644 --- a/contracts/core/primitives/group/GroupCore.sol +++ b/contracts/core/primitives/group/GroupCore.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.17; +pragma solidity ^0.8.26; import {Membership} from "contracts/core/interfaces/IGroup.sol"; diff --git a/contracts/core/primitives/group/RuleBasedGroup.sol b/contracts/core/primitives/group/RuleBasedGroup.sol index 368cd8fd..a251710e 100644 --- a/contracts/core/primitives/group/RuleBasedGroup.sol +++ b/contracts/core/primitives/group/RuleBasedGroup.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IGroupRule} from "contracts/core/interfaces/IGroupRule.sol"; import {IGroup} from "contracts/core/interfaces/IGroup.sol"; diff --git a/contracts/core/primitives/namespace/LensUsernameTokenURIProvider.sol b/contracts/core/primitives/namespace/LensUsernameTokenURIProvider.sol index fa225812..6095a2c7 100644 --- a/contracts/core/primitives/namespace/LensUsernameTokenURIProvider.sol +++ b/contracts/core/primitives/namespace/LensUsernameTokenURIProvider.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {ITokenURIProvider} from "contracts/core/interfaces/ITokenURIProvider.sol"; import "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol"; diff --git a/contracts/core/primitives/namespace/Namespace.sol b/contracts/core/primitives/namespace/Namespace.sol index 29fb239d..d1e6e928 100644 --- a/contracts/core/primitives/namespace/Namespace.sol +++ b/contracts/core/primitives/namespace/Namespace.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {NamespaceCore as Core} from "contracts/core/primitives/namespace/NamespaceCore.sol"; import {INamespace} from "contracts/core/interfaces/INamespace.sol"; @@ -95,12 +95,12 @@ contract Namespace is function createAndAssignUsername( address account, - string calldata username, + string memory username, KeyValue[] calldata customParams, RuleProcessingParams[] calldata unassigningProcessingParams, RuleProcessingParams[] calldata creationProcessingParams, RuleProcessingParams[] calldata assigningProcessingParams, - KeyValue[] calldata extraData + KeyValue[] memory extraData ) external { require(msg.sender == account); // msg.sender must be the account uint256 id = _computeId(username); diff --git a/contracts/core/primitives/namespace/NamespaceCore.sol b/contracts/core/primitives/namespace/NamespaceCore.sol index 10cca5e0..6b6403da 100644 --- a/contracts/core/primitives/namespace/NamespaceCore.sol +++ b/contracts/core/primitives/namespace/NamespaceCore.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; library NamespaceCore { // Storage diff --git a/contracts/core/primitives/namespace/RuleBasedNamespace.sol b/contracts/core/primitives/namespace/RuleBasedNamespace.sol index dbdff676..7af1eaa5 100644 --- a/contracts/core/primitives/namespace/RuleBasedNamespace.sol +++ b/contracts/core/primitives/namespace/RuleBasedNamespace.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {INamespaceRule} from "contracts/core/interfaces/INamespaceRule.sol"; import {RulesStorage, RulesLib} from "contracts/core/libraries/RulesLib.sol"; diff --git a/contracts/core/types/Events.sol b/contracts/core/types/Events.sol index 67299712..9b2ca52b 100644 --- a/contracts/core/types/Events.sol +++ b/contracts/core/types/Events.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.17; +pragma solidity ^0.8.26; library Events { event Lens_Contract_Deployed( diff --git a/contracts/core/types/Types.sol b/contracts/core/types/Types.sol index abd94892..b8cf4f33 100644 --- a/contracts/core/types/Types.sol +++ b/contracts/core/types/Types.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.17; +pragma solidity ^0.8.26; struct KeyValue { bytes32 key; diff --git a/contracts/core/upgradeability/Beacon.sol b/contracts/core/upgradeability/Beacon.sol index 962c7687..00114db2 100644 --- a/contracts/core/upgradeability/Beacon.sol +++ b/contracts/core/upgradeability/Beacon.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {Ownable} from "contracts/core/access/Ownable.sol"; import {IVersionedBeacon} from "contracts/core/interfaces/IVersionedBeacon.sol"; diff --git a/contracts/core/upgradeability/BeaconProxy.sol b/contracts/core/upgradeability/BeaconProxy.sol index 06cfcbf0..64e91ad7 100644 --- a/contracts/core/upgradeability/BeaconProxy.sol +++ b/contracts/core/upgradeability/BeaconProxy.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IVersionedBeacon} from "contracts/core/interfaces/IVersionedBeacon.sol"; diff --git a/contracts/core/upgradeability/Initializable.sol b/contracts/core/upgradeability/Initializable.sol index a9ff385b..ab1f658d 100644 --- a/contracts/core/upgradeability/Initializable.sol +++ b/contracts/core/upgradeability/Initializable.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; abstract contract Initializable { // Storage diff --git a/contracts/core/upgradeability/Lock.sol b/contracts/core/upgradeability/Lock.sol index 591586e2..2fa9793d 100644 --- a/contracts/core/upgradeability/Lock.sol +++ b/contracts/core/upgradeability/Lock.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {ILock} from "contracts/core/interfaces/ILock.sol"; import {Ownable} from "contracts/core/access/Ownable.sol"; diff --git a/contracts/core/upgradeability/ProxyAdmin.sol b/contracts/core/upgradeability/ProxyAdmin.sol index fa90f3f1..a6dbc587 100644 --- a/contracts/core/upgradeability/ProxyAdmin.sol +++ b/contracts/core/upgradeability/ProxyAdmin.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {ILock} from "contracts/core/interfaces/ILock.sol"; import {BeaconProxy} from "contracts/core/upgradeability/BeaconProxy.sol"; diff --git a/contracts/extensions/access/OwnerAdminOnlyAccessControl.sol b/contracts/extensions/access/OwnerAdminOnlyAccessControl.sol index 0fe94d82..d0129823 100644 --- a/contracts/extensions/access/OwnerAdminOnlyAccessControl.sol +++ b/contracts/extensions/access/OwnerAdminOnlyAccessControl.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {Events} from "contracts/core/types/Events.sol"; import {RoleBasedAccessControl} from "contracts/core/access/RoleBasedAccessControl.sol"; diff --git a/contracts/extensions/access/PermissionlessAccessControl.sol b/contracts/extensions/access/PermissionlessAccessControl.sol index 459bb444..0ef6d7dd 100644 --- a/contracts/extensions/access/PermissionlessAccessControl.sol +++ b/contracts/extensions/access/PermissionlessAccessControl.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IAccessControl} from "contracts/core/interfaces/IAccessControl.sol"; diff --git a/contracts/extensions/account/Account.sol b/contracts/extensions/account/Account.sol index dfaffd2a..3d2ddc48 100644 --- a/contracts/extensions/account/Account.sol +++ b/contracts/extensions/account/Account.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.12; +pragma solidity ^0.8.26; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; diff --git a/contracts/extensions/account/IAccount.sol b/contracts/extensions/account/IAccount.sol index 7333c774..a0ec1331 100644 --- a/contracts/extensions/account/IAccount.sol +++ b/contracts/extensions/account/IAccount.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.17; +pragma solidity ^0.8.26; import {SourceStamp, KeyValue} from "contracts/core/types/Types.sol"; import {IMetadataBased} from "contracts/core/interfaces/IMetadataBased.sol"; diff --git a/contracts/extensions/actions/ActionHub.sol b/contracts/extensions/actions/ActionHub.sol index 54e7cb9c..24706a13 100644 --- a/contracts/extensions/actions/ActionHub.sol +++ b/contracts/extensions/actions/ActionHub.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {KeyValue} from "contracts/core/types/Types.sol"; diff --git a/contracts/extensions/factories/AccessControlFactory.sol b/contracts/extensions/factories/AccessControlFactory.sol index a753ca10..2ec4658e 100644 --- a/contracts/extensions/factories/AccessControlFactory.sol +++ b/contracts/extensions/factories/AccessControlFactory.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IRoleBasedAccessControl} from "contracts/core/interfaces/IRoleBasedAccessControl.sol"; import {OwnerAdminOnlyAccessControl} from "contracts/extensions/access/OwnerAdminOnlyAccessControl.sol"; diff --git a/contracts/extensions/factories/AccountFactory.sol b/contracts/extensions/factories/AccountFactory.sol index b20e1938..5a959517 100644 --- a/contracts/extensions/factories/AccountFactory.sol +++ b/contracts/extensions/factories/AccountFactory.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {Account, AccountManagerPermissions} from "contracts/extensions/account/Account.sol"; import {KeyValue, SourceStamp} from "contracts/core/types/Types.sol"; diff --git a/contracts/extensions/factories/AppFactory.sol b/contracts/extensions/factories/AppFactory.sol index 7fe3d969..579af819 100644 --- a/contracts/extensions/factories/AppFactory.sol +++ b/contracts/extensions/factories/AppFactory.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IAccessControl} from "contracts/core/interfaces/IAccessControl.sol"; import {AppInitialProperties, App} from "contracts/extensions/primitives/app/App.sol"; diff --git a/contracts/extensions/factories/FeedFactory.sol b/contracts/extensions/factories/FeedFactory.sol index 77b2d678..67b74abe 100644 --- a/contracts/extensions/factories/FeedFactory.sol +++ b/contracts/extensions/factories/FeedFactory.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IAccessControl} from "contracts/core/interfaces/IAccessControl.sol"; import {Feed} from "contracts/core/primitives/feed/Feed.sol"; diff --git a/contracts/extensions/factories/GraphFactory.sol b/contracts/extensions/factories/GraphFactory.sol index bcdafde8..8548658a 100644 --- a/contracts/extensions/factories/GraphFactory.sol +++ b/contracts/extensions/factories/GraphFactory.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IAccessControl} from "contracts/core/interfaces/IAccessControl.sol"; import {Graph} from "contracts/core/primitives/graph/Graph.sol"; diff --git a/contracts/extensions/factories/GroupFactory.sol b/contracts/extensions/factories/GroupFactory.sol index 38fc76bf..b9583949 100644 --- a/contracts/extensions/factories/GroupFactory.sol +++ b/contracts/extensions/factories/GroupFactory.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IAccessControl} from "contracts/core/interfaces/IAccessControl.sol"; import {Group} from "contracts/core/primitives/group/Group.sol"; diff --git a/contracts/extensions/factories/LensFactory.sol b/contracts/extensions/factories/LensFactory.sol index 7b4f420e..f20da6da 100644 --- a/contracts/extensions/factories/LensFactory.sol +++ b/contracts/extensions/factories/LensFactory.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IRoleBasedAccessControl} from "contracts/core/interfaces/IRoleBasedAccessControl.sol"; import {IAccessControl} from "contracts/core/interfaces/IAccessControl.sol"; diff --git a/contracts/extensions/factories/NamespaceFactory.sol b/contracts/extensions/factories/NamespaceFactory.sol index c3eec2d5..c55fac17 100644 --- a/contracts/extensions/factories/NamespaceFactory.sol +++ b/contracts/extensions/factories/NamespaceFactory.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IAccessControl} from "contracts/core/interfaces/IAccessControl.sol"; import {Namespace} from "contracts/core/primitives/namespace/Namespace.sol"; diff --git a/contracts/extensions/factories/PrimitiveFactory.sol b/contracts/extensions/factories/PrimitiveFactory.sol index f846b224..ea6d8392 100644 --- a/contracts/extensions/factories/PrimitiveFactory.sol +++ b/contracts/extensions/factories/PrimitiveFactory.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IAccessControl} from "contracts/core/interfaces/IAccessControl.sol"; import {PermissionlessAccessControl} from "contracts/extensions/access/PermissionlessAccessControl.sol"; diff --git a/contracts/extensions/primitives/app/App.sol b/contracts/extensions/primitives/app/App.sol index 7cf86ed6..5b135e54 100644 --- a/contracts/extensions/primitives/app/App.sol +++ b/contracts/extensions/primitives/app/App.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IAccessControl} from "contracts/core/interfaces/IAccessControl.sol"; import {IApp} from "contracts/extensions/primitives/app/IApp.sol"; diff --git a/contracts/extensions/primitives/app/AppCore.sol b/contracts/extensions/primitives/app/AppCore.sol index a8acae33..2f7db9cc 100644 --- a/contracts/extensions/primitives/app/AppCore.sol +++ b/contracts/extensions/primitives/app/AppCore.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.17; +pragma solidity ^0.8.26; import "contracts/core/libraries/ExtraDataLib.sol"; diff --git a/contracts/extensions/primitives/app/IApp.sol b/contracts/extensions/primitives/app/IApp.sol index c8c17949..a7f7bcb6 100644 --- a/contracts/extensions/primitives/app/IApp.sol +++ b/contracts/extensions/primitives/app/IApp.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IMetadataBased} from "contracts/core/interfaces/IMetadataBased.sol"; import {KeyValue} from "contracts/core/types/Types.sol"; diff --git a/contracts/extensions/registries/CurrencyRegistry_MockEvents.sol b/contracts/extensions/registries/CurrencyRegistry_MockEvents.sol index 157d6b13..610b169d 100644 --- a/contracts/extensions/registries/CurrencyRegistry_MockEvents.sol +++ b/contracts/extensions/registries/CurrencyRegistry_MockEvents.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; contract CurrencyRegistry { event Lens_Currency_Registered(address indexed currency, string name, string symbol, uint8 decimals); diff --git a/contracts/extensions/registries/PostActionsRegistry_MockEvents.sol b/contracts/extensions/registries/PostActionsRegistry_MockEvents.sol index 7be9a9ea..86ed1cea 100644 --- a/contracts/extensions/registries/PostActionsRegistry_MockEvents.sol +++ b/contracts/extensions/registries/PostActionsRegistry_MockEvents.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; contract PostActionsRegistry { // This is emitted when a DEV signals they developed a new PostAction that someone can use diff --git a/contracts/migration/MigrationFeed.sol b/contracts/migration/MigrationFeed.sol index 17b8fd6c..234655b7 100644 --- a/contracts/migration/MigrationFeed.sol +++ b/contracts/migration/MigrationFeed.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {KeyValue, RuleProcessingParams} from "contracts/core/types/Types.sol"; import {CreatePostParams} from "contracts/core/interfaces/IFeed.sol"; diff --git a/contracts/migration/MigrationGraph.sol b/contracts/migration/MigrationGraph.sol index a8d1436c..e990bdb1 100644 --- a/contracts/migration/MigrationGraph.sol +++ b/contracts/migration/MigrationGraph.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {GraphCore as Core} from "contracts/core/primitives/graph/GraphCore.sol"; import {Graph} from "contracts/core/primitives/graph/Graph.sol"; diff --git a/contracts/rules/base/AccountBlockingRule.sol b/contracts/rules/base/AccountBlockingRule.sol index f106be40..f4bb4744 100644 --- a/contracts/rules/base/AccountBlockingRule.sol +++ b/contracts/rules/base/AccountBlockingRule.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.17; +pragma solidity ^0.8.26; import {IFeedRule} from "contracts/core/interfaces/IFeedRule.sol"; import {IGraphRule} from "contracts/core/interfaces/IGraphRule.sol"; diff --git a/contracts/rules/base/RestrictedSignersRule.sol b/contracts/rules/base/RestrictedSignersRule.sol index 12b2f9b1..443834e9 100644 --- a/contracts/rules/base/RestrictedSignersRule.sol +++ b/contracts/rules/base/RestrictedSignersRule.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {EIP712EncodingLib} from "contracts/core/libraries/EIP712EncodingLib.sol"; import {IERC1271} from "@openzeppelin/contracts/interfaces/IERC1271.sol"; diff --git a/contracts/rules/base/SimplePaymentRule.sol b/contracts/rules/base/SimplePaymentRule.sol index dd94f830..49854b97 100644 --- a/contracts/rules/base/SimplePaymentRule.sol +++ b/contracts/rules/base/SimplePaymentRule.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; diff --git a/contracts/rules/base/TokenGatedRule.sol b/contracts/rules/base/TokenGatedRule.sol index 861835bc..30e0801f 100644 --- a/contracts/rules/base/TokenGatedRule.sol +++ b/contracts/rules/base/TokenGatedRule.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IERC1155} from "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; import {MetadataBased} from "contracts/core/base/MetadataBased.sol"; diff --git a/contracts/rules/feed/GroupGatedFeedRule.sol b/contracts/rules/feed/GroupGatedFeedRule.sol index c489acff..bb306856 100644 --- a/contracts/rules/feed/GroupGatedFeedRule.sol +++ b/contracts/rules/feed/GroupGatedFeedRule.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {CreatePostParams, EditPostParams} from "contracts/core/interfaces/IFeed.sol"; import {IFeedRule} from "contracts/core/interfaces/IFeedRule.sol"; diff --git a/contracts/rules/feed/RestrictedSignersFeedRule.sol b/contracts/rules/feed/RestrictedSignersFeedRule.sol index 08672f0a..4bee003a 100644 --- a/contracts/rules/feed/RestrictedSignersFeedRule.sol +++ b/contracts/rules/feed/RestrictedSignersFeedRule.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {CreatePostParams, EditPostParams} from "contracts/core/interfaces/IFeed.sol"; import {IFeedRule} from "contracts/core/interfaces/IFeedRule.sol"; diff --git a/contracts/rules/feed/SimplePaymentFeedRule.sol b/contracts/rules/feed/SimplePaymentFeedRule.sol index 77e66ed0..252fb763 100644 --- a/contracts/rules/feed/SimplePaymentFeedRule.sol +++ b/contracts/rules/feed/SimplePaymentFeedRule.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {CreatePostParams, EditPostParams} from "contracts/core/interfaces/IFeed.sol"; import {IFeedRule} from "contracts/core/interfaces/IFeedRule.sol"; diff --git a/contracts/rules/feed/TokenGatedFeedRule.sol b/contracts/rules/feed/TokenGatedFeedRule.sol index dda22ca7..042490b4 100644 --- a/contracts/rules/feed/TokenGatedFeedRule.sol +++ b/contracts/rules/feed/TokenGatedFeedRule.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {CreatePostParams, EditPostParams} from "contracts/core/interfaces/IFeed.sol"; import {IFeedRule} from "contracts/core/interfaces/IFeedRule.sol"; diff --git a/contracts/rules/follow/SimplePaymentFollowRule.sol b/contracts/rules/follow/SimplePaymentFollowRule.sol index 7896adfa..cd2a59f9 100644 --- a/contracts/rules/follow/SimplePaymentFollowRule.sol +++ b/contracts/rules/follow/SimplePaymentFollowRule.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IFollowRule} from "contracts/core/interfaces/IFollowRule.sol"; import {SimplePaymentRule} from "contracts/rules/base/SimplePaymentRule.sol"; diff --git a/contracts/rules/follow/TokenGatedFollowRule.sol b/contracts/rules/follow/TokenGatedFollowRule.sol index 94b28acb..b06267fc 100644 --- a/contracts/rules/follow/TokenGatedFollowRule.sol +++ b/contracts/rules/follow/TokenGatedFollowRule.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IFollowRule} from "contracts/core/interfaces/IFollowRule.sol"; import {TokenGatedRule} from "contracts/rules/base/TokenGatedRule.sol"; diff --git a/contracts/rules/graph/GroupGatedGraphRule.sol b/contracts/rules/graph/GroupGatedGraphRule.sol index ade51593..4855215d 100644 --- a/contracts/rules/graph/GroupGatedGraphRule.sol +++ b/contracts/rules/graph/GroupGatedGraphRule.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IGraphRule} from "contracts/core/interfaces/IGraphRule.sol"; import {IAccessControl} from "contracts/core/interfaces/IAccessControl.sol"; diff --git a/contracts/rules/graph/RestrictedSignersGraphRule.sol b/contracts/rules/graph/RestrictedSignersGraphRule.sol index d3f2c3df..1d159a9d 100644 --- a/contracts/rules/graph/RestrictedSignersGraphRule.sol +++ b/contracts/rules/graph/RestrictedSignersGraphRule.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IGraphRule} from "contracts/core/interfaces/IGraphRule.sol"; import {RestrictedSignersRule, EIP712Signature} from "contracts/rules/base/RestrictedSignersRule.sol"; diff --git a/contracts/rules/graph/TokenGatedGraphRule.sol b/contracts/rules/graph/TokenGatedGraphRule.sol index 16c4cf2d..176343dc 100644 --- a/contracts/rules/graph/TokenGatedGraphRule.sol +++ b/contracts/rules/graph/TokenGatedGraphRule.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IGraphRule} from "contracts/core/interfaces/IGraphRule.sol"; import {TokenGatedRule} from "contracts/rules/base/TokenGatedRule.sol"; diff --git a/contracts/rules/group/BanMemberGroupRule.sol b/contracts/rules/group/BanMemberGroupRule.sol index 7e23e458..f60a144e 100644 --- a/contracts/rules/group/BanMemberGroupRule.sol +++ b/contracts/rules/group/BanMemberGroupRule.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IGroupRule} from "contracts/core/interfaces/IGroupRule.sol"; import {IAccessControl} from "contracts/core/interfaces/IAccessControl.sol"; diff --git a/contracts/rules/group/MembershipApprovalGroupRule.sol b/contracts/rules/group/MembershipApprovalGroupRule.sol index 8c32cec6..835c01fb 100644 --- a/contracts/rules/group/MembershipApprovalGroupRule.sol +++ b/contracts/rules/group/MembershipApprovalGroupRule.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IGroupRule} from "contracts/core/interfaces/IGroupRule.sol"; import {IAccessControl} from "contracts/core/interfaces/IAccessControl.sol"; diff --git a/contracts/rules/group/SimplePaymentGroupRule.sol b/contracts/rules/group/SimplePaymentGroupRule.sol index f3338c46..5f75f7f1 100644 --- a/contracts/rules/group/SimplePaymentGroupRule.sol +++ b/contracts/rules/group/SimplePaymentGroupRule.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IGroupRule} from "contracts/core/interfaces/IGroupRule.sol"; import {SimplePaymentRule} from "contracts/rules/base/SimplePaymentRule.sol"; diff --git a/contracts/rules/group/TokenGatedGroupRule.sol b/contracts/rules/group/TokenGatedGroupRule.sol index 56b49a05..667c9b88 100644 --- a/contracts/rules/group/TokenGatedGroupRule.sol +++ b/contracts/rules/group/TokenGatedGroupRule.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IGroupRule} from "contracts/core/interfaces/IGroupRule.sol"; import {TokenGatedRule} from "contracts/rules/base/TokenGatedRule.sol"; diff --git a/contracts/rules/namespace/SimplePaymentNamespaceRule.sol b/contracts/rules/namespace/SimplePaymentNamespaceRule.sol index e1768ae7..10dc369b 100644 --- a/contracts/rules/namespace/SimplePaymentNamespaceRule.sol +++ b/contracts/rules/namespace/SimplePaymentNamespaceRule.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IAccessControl} from "contracts/core/interfaces/IAccessControl.sol"; import {INamespaceRule} from "contracts/core/interfaces/INamespaceRule.sol"; diff --git a/contracts/rules/namespace/TokenGatedNamespaceRule.sol b/contracts/rules/namespace/TokenGatedNamespaceRule.sol index b4c457b7..18347ee5 100644 --- a/contracts/rules/namespace/TokenGatedNamespaceRule.sol +++ b/contracts/rules/namespace/TokenGatedNamespaceRule.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IAccessControl} from "contracts/core/interfaces/IAccessControl.sol"; import {INamespaceRule} from "contracts/core/interfaces/INamespaceRule.sol"; diff --git a/contracts/rules/namespace/UsernameCharsetNamespaceRule.sol b/contracts/rules/namespace/UsernameCharsetNamespaceRule.sol index 6e77f932..a58b8826 100644 --- a/contracts/rules/namespace/UsernameCharsetNamespaceRule.sol +++ b/contracts/rules/namespace/UsernameCharsetNamespaceRule.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IAccessControl} from "contracts/core/interfaces/IAccessControl.sol"; import {INamespaceRule} from "contracts/core/interfaces/INamespaceRule.sol"; diff --git a/contracts/rules/namespace/UsernameLengthNamespaceRule.sol b/contracts/rules/namespace/UsernameLengthNamespaceRule.sol index 8436f883..0e5b8e93 100644 --- a/contracts/rules/namespace/UsernameLengthNamespaceRule.sol +++ b/contracts/rules/namespace/UsernameLengthNamespaceRule.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IAccessControl} from "contracts/core/interfaces/IAccessControl.sol"; import {INamespaceRule} from "contracts/core/interfaces/INamespaceRule.sol"; diff --git a/contracts/rules/namespace/UsernameReservedNamespaceRule.sol b/contracts/rules/namespace/UsernameReservedNamespaceRule.sol index 7b965652..9ce13e03 100644 --- a/contracts/rules/namespace/UsernameReservedNamespaceRule.sol +++ b/contracts/rules/namespace/UsernameReservedNamespaceRule.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IAccessControl} from "contracts/core/interfaces/IAccessControl.sol"; import {INamespaceRule} from "contracts/core/interfaces/INamespaceRule.sol"; diff --git a/contracts/rules/post/FollowersOnlyPostRule.sol b/contracts/rules/post/FollowersOnlyPostRule.sol index 24e25ddc..ed2b4c20 100644 --- a/contracts/rules/post/FollowersOnlyPostRule.sol +++ b/contracts/rules/post/FollowersOnlyPostRule.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.0; +pragma solidity ^0.8.26; import {IPostRule} from "contracts/core/interfaces/IPostRule.sol"; import {IGraph} from "contracts/core/interfaces/IGraph.sol"; diff --git a/foundry.toml b/foundry.toml index 9a9e0308..1abb8d9a 100644 --- a/foundry.toml +++ b/foundry.toml @@ -4,7 +4,7 @@ out = 'out' libs = ['node_modules', 'lib'] test = 'test' cache_path = 'cache_forge' -solc_version = '0.8.17' +solc_version = '0.8.28' # [profile.default.zksync] # # Compile contracts for zkVM diff --git a/hardhat.config.ts b/hardhat.config.ts index 282ea9df..c0d301b7 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -40,7 +40,7 @@ const config: HardhatUserConfig = { }, }, solidity: { - version: '0.8.17', + version: '0.8.28', }, }; diff --git a/test/Account.t.sol b/test/Account.t.sol index bf8aceaa..3b29a926 100644 --- a/test/Account.t.sol +++ b/test/Account.t.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity 0.8.17; +pragma solidity ^0.8.26; import "forge-std/Test.sol"; import "./helpers/TypeHelpers.sol"; diff --git a/test/access-control/OwnerAdminOnlyAccessControl.t.sol b/test/access-control/OwnerAdminOnlyAccessControl.t.sol index 6a7f0ee2..ad8af061 100644 --- a/test/access-control/OwnerAdminOnlyAccessControl.t.sol +++ b/test/access-control/OwnerAdminOnlyAccessControl.t.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity 0.8.17; +pragma solidity ^0.8.26; import "forge-std/Test.sol"; import {OwnerAdminOnlyAccessControl} from "contracts/extensions/access/OwnerAdminOnlyAccessControl.sol"; diff --git a/test/app/App.t.sol b/test/app/App.t.sol index 8efaba93..a4629e2d 100644 --- a/test/app/App.t.sol +++ b/test/app/App.t.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity 0.8.17; +pragma solidity ^0.8.26; import "forge-std/Test.sol"; import "../helpers/TypeHelpers.sol"; diff --git a/test/factories/LensFactory.t.sol b/test/factories/LensFactory.t.sol index ab845043..d079b561 100644 --- a/test/factories/LensFactory.t.sol +++ b/test/factories/LensFactory.t.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity 0.8.17; +pragma solidity ^0.8.26; import "forge-std/Test.sol"; import {LensFactory} from "@extensions/factories/LensFactory.sol"; diff --git a/test/helpers/BaseDeployments.sol b/test/helpers/BaseDeployments.sol index 03221485..88d97aab 100644 --- a/test/helpers/BaseDeployments.sol +++ b/test/helpers/BaseDeployments.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity 0.8.17; +pragma solidity ^0.8.26; import "forge-std/Test.sol"; diff --git a/test/helpers/TypeHelpers.sol b/test/helpers/TypeHelpers.sol index f9d9d2b1..0b8f4664 100644 --- a/test/helpers/TypeHelpers.sol +++ b/test/helpers/TypeHelpers.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity ^0.8.13; +pragma solidity ^0.8.26; import {RuleChange, RuleProcessingParams, SourceStamp, KeyValue} from "contracts/core/types/Types.sol"; diff --git a/test/primitives/Feed.t.sol b/test/primitives/Feed.t.sol index f92036d8..caaaeeb8 100644 --- a/test/primitives/Feed.t.sol +++ b/test/primitives/Feed.t.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity 0.8.17; +pragma solidity ^0.8.26; import "forge-std/Test.sol"; import {IAccessControl} from "@core/interfaces/IAccessControl.sol"; diff --git a/test/primitives/Graph.t.sol b/test/primitives/Graph.t.sol index f789367c..08b88dbd 100644 --- a/test/primitives/Graph.t.sol +++ b/test/primitives/Graph.t.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity 0.8.17; +pragma solidity ^0.8.26; import "forge-std/Test.sol"; import {IAccessControl} from "@core/interfaces/IAccessControl.sol"; diff --git a/test/primitives/Group.t.sol b/test/primitives/Group.t.sol index 3fc110f9..98c30efe 100644 --- a/test/primitives/Group.t.sol +++ b/test/primitives/Group.t.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity 0.8.17; +pragma solidity ^0.8.26; import "forge-std/Test.sol"; import {IAccessControl} from "@core/interfaces/IAccessControl.sol"; diff --git a/test/primitives/Namespace.t.sol b/test/primitives/Namespace.t.sol index 4c4768d6..9e097c7e 100644 --- a/test/primitives/Namespace.t.sol +++ b/test/primitives/Namespace.t.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: UNLICENSED // Copyright (C) 2024 Lens Labs. All Rights Reserved. -pragma solidity 0.8.17; +pragma solidity ^0.8.26; import "forge-std/Test.sol"; import {IAccessControl} from "@core/interfaces/IAccessControl.sol"; From f3e80a08e0212f59eaa416537f0e7863bf9f4056 Mon Sep 17 00:00:00 2001 From: Alan Donoso Naumczuk Date: Thu, 9 Jan 2025 19:37:28 -0300 Subject: [PATCH 04/41] misc: Custom Errors added on every revert case --- .../actions/account/TippingAccountAction.sol | 3 +- .../account/base/BaseAccountAction.sol | 3 +- contracts/actions/base/BaseAction.sol | 7 +-- contracts/actions/post/TippingPostAction.sol | 3 +- .../actions/post/base/BasePostAction.sol | 3 +- .../post/collect/LensCollectedPost.sol | 9 ++-- .../post/collect/SimpleCollectAction.sol | 33 +++++++------ contracts/core/access/Ownable.sol | 4 +- .../core/access/RoleBasedAccessControl.sol | 27 +++++------ contracts/core/base/BaseSource.sol | 9 ++-- contracts/core/base/LensERC721.sol | 40 ++++++++-------- contracts/core/base/MetadataBased.sol | 3 +- contracts/core/base/RuleBasedPrimitive.sol | 7 +-- contracts/core/libraries/AccessControlLib.sol | 11 ++++- contracts/core/libraries/CallLib.sol | 6 ++- contracts/core/libraries/RulesLib.sol | 16 +++++-- contracts/core/primitives/feed/Feed.sol | 21 +++++---- contracts/core/primitives/feed/FeedCore.sol | 17 ++++--- .../core/primitives/feed/RuleBasedFeed.sol | 17 +++---- contracts/core/primitives/graph/Graph.sol | 11 +++-- contracts/core/primitives/graph/GraphCore.sol | 11 +++-- .../core/primitives/graph/RuleBasedGraph.sol | 13 +++--- contracts/core/primitives/group/Group.sol | 11 +++-- contracts/core/primitives/group/GroupCore.sol | 5 +- .../core/primitives/group/RuleBasedGroup.sol | 5 +- .../core/primitives/namespace/Namespace.sol | 19 ++++---- .../primitives/namespace/NamespaceCore.sol | 18 ++++---- .../namespace/RuleBasedNamespace.sol | 5 +- contracts/core/types/Errors.sol | 46 +++++++++++++++++++ contracts/core/upgradeability/Beacon.sol | 9 ++-- contracts/core/upgradeability/BeaconProxy.sol | 17 +++---- .../core/upgradeability/Initializable.sol | 4 +- contracts/core/upgradeability/ProxyAdmin.sol | 15 +++--- .../access/OwnerAdminOnlyAccessControl.sol | 5 +- contracts/extensions/account/Account.sol | 41 ++++++----------- contracts/extensions/actions/ActionHub.sol | 5 +- .../extensions/factories/LensFactory.sol | 11 +++-- .../extensions/primitives/app/AppCore.sol | 17 +++---- contracts/migration/MigrationFeed.sol | 17 +++---- contracts/rules/base/AccountBlockingRule.sol | 23 +++++----- .../rules/base/RestrictedSignersRule.sol | 23 +++++----- contracts/rules/base/SimplePaymentRule.sol | 11 +++-- contracts/rules/base/TokenGatedRule.sol | 7 +-- contracts/rules/feed/GroupGatedFeedRule.sol | 9 ++-- .../rules/feed/SimplePaymentFeedRule.sol | 7 +-- contracts/rules/feed/TokenGatedFeedRule.sol | 7 +-- contracts/rules/graph/GroupGatedGraphRule.sol | 7 +-- contracts/rules/graph/TokenGatedGraphRule.sol | 5 +- contracts/rules/group/BanMemberGroupRule.sol | 11 +++-- .../group/MembershipApprovalGroupRule.sol | 17 +++---- .../rules/group/SimplePaymentGroupRule.sol | 7 +-- contracts/rules/group/TokenGatedGroupRule.sol | 7 +-- .../UsernameCharsetNamespaceRule.sol | 36 +++++---------- .../namespace/UsernameLengthNamespaceRule.sol | 14 +++--- .../UsernameReservedNamespaceRule.sol | 16 +++++-- .../rules/post/FollowersOnlyPostRule.sol | 12 +++-- test/Account.t.sol | 9 ++-- 57 files changed, 420 insertions(+), 332 deletions(-) create mode 100644 contracts/core/types/Errors.sol diff --git a/contracts/actions/account/TippingAccountAction.sol b/contracts/actions/account/TippingAccountAction.sol index aa25729b..67d2e3dc 100644 --- a/contracts/actions/account/TippingAccountAction.sol +++ b/contracts/actions/account/TippingAccountAction.sol @@ -7,6 +7,7 @@ import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {KeyValue} from "contracts/core/types/Types.sol"; import {MetadataBased} from "contracts/core/base/MetadataBased.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; contract TippingAccountAction is BaseAccountAction, MetadataBased { using SafeERC20 for IERC20; @@ -40,7 +41,7 @@ contract TippingAccountAction is BaseAccountAction, MetadataBased { erc20Token = abi.decode(params[i].value, (address)); } } - require(tipAmount > 0); + require(tipAmount > 0, Errors.InvalidParameter()); IERC20(erc20Token).safeTransferFrom(originalMsgSender, account, tipAmount); return ""; } diff --git a/contracts/actions/account/base/BaseAccountAction.sol b/contracts/actions/account/base/BaseAccountAction.sol index 9aab041d..63ebcbbd 100644 --- a/contracts/actions/account/base/BaseAccountAction.sol +++ b/contracts/actions/account/base/BaseAccountAction.sol @@ -5,6 +5,7 @@ pragma solidity ^0.8.26; import {KeyValue} from "contracts/core/types/Types.sol"; import {BaseAction} from "contracts/actions/base/BaseAction.sol"; import {IAccountAction} from "contracts/extensions/actions/ActionHub.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; abstract contract BaseAccountAction is BaseAction, IAccountAction { constructor(address actionHub) BaseAction(actionHub) {} @@ -55,6 +56,6 @@ abstract contract BaseAccountAction is BaseAction, IAccountAction { bool, /* isDisabled */ KeyValue[] calldata /* params */ ) internal virtual returns (bytes memory) { - revert(); + revert Errors.NotImplemented(); } } diff --git a/contracts/actions/base/BaseAction.sol b/contracts/actions/base/BaseAction.sol index b9310448..61f00d4d 100644 --- a/contracts/actions/base/BaseAction.sol +++ b/contracts/actions/base/BaseAction.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.26; import {UNIVERSAL_ACTION_MAGIC_VALUE} from "contracts/extensions/actions/ActionHub.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; abstract contract BaseAction { address immutable ACTION_HUB; @@ -11,7 +12,7 @@ abstract contract BaseAction { bytes32 constant STORAGE__ACTION_CONFIGURED = 0x852bead036b7ef35b8026346140cc688bafe817a6c3491812e6d994b1bcda6d9; modifier onlyActionHub() { - require(msg.sender == ACTION_HUB); + require(msg.sender == ACTION_HUB, Errors.InvalidMsgSender()); _; } @@ -24,8 +25,8 @@ abstract contract BaseAction { assembly { configured := sload(STORAGE__ACTION_CONFIGURED) } - require(!configured); - require(originalMsgSender == address(0)); + require(!configured, Errors.RedundantStateChange()); + require(originalMsgSender == address(0), Errors.InvalidParameter()); assembly { sstore(STORAGE__ACTION_CONFIGURED, 1) } diff --git a/contracts/actions/post/TippingPostAction.sol b/contracts/actions/post/TippingPostAction.sol index 0977e03a..8766d1b2 100644 --- a/contracts/actions/post/TippingPostAction.sol +++ b/contracts/actions/post/TippingPostAction.sol @@ -8,6 +8,7 @@ import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol import {KeyValue} from "contracts/core/types/Types.sol"; import {IFeed} from "contracts/core/interfaces/IFeed.sol"; import {MetadataBased} from "contracts/core/base/MetadataBased.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; contract TippingPostAction is BasePostAction, MetadataBased { using SafeERC20 for IERC20; @@ -41,7 +42,7 @@ contract TippingPostAction is BasePostAction, MetadataBased { erc20Token = abi.decode(params[i].value, (address)); } } - require(tipAmount > 0); + require(tipAmount > 0, Errors.InvalidParameter()); address account = IFeed(feed).getPostAuthor(postId); IERC20(erc20Token).safeTransferFrom(originalMsgSender, account, tipAmount); return abi.encode(account); diff --git a/contracts/actions/post/base/BasePostAction.sol b/contracts/actions/post/base/BasePostAction.sol index c8178c14..ebd50b80 100644 --- a/contracts/actions/post/base/BasePostAction.sol +++ b/contracts/actions/post/base/BasePostAction.sol @@ -5,6 +5,7 @@ pragma solidity ^0.8.26; import {KeyValue} from "contracts/core/types/Types.sol"; import {BaseAction} from "contracts/actions/base/BaseAction.sol"; import {IPostAction} from "contracts/extensions/actions/ActionHub.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; abstract contract BasePostAction is BaseAction, IPostAction { constructor(address actionHub) BaseAction(actionHub) {} @@ -58,6 +59,6 @@ abstract contract BasePostAction is BaseAction, IPostAction { bool, /* isDisabled */ KeyValue[] calldata /* params */ ) internal virtual returns (bytes memory) { - revert(); + revert Errors.NotImplemented(); } } diff --git a/contracts/actions/post/collect/LensCollectedPost.sol b/contracts/actions/post/collect/LensCollectedPost.sol index 8f82168f..a1ca5ae7 100644 --- a/contracts/actions/post/collect/LensCollectedPost.sol +++ b/contracts/actions/post/collect/LensCollectedPost.sol @@ -6,6 +6,7 @@ import "contracts/core/base/LensERC721.sol"; import {IERC7572} from "contracts/actions/post/collect/IERC7572.sol"; import {IFeed} from "contracts/core/interfaces/IFeed.sol"; import {ITokenURIProvider} from "contracts/core/interfaces/ITokenURIProvider.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; /** * @notice A contract that represents a Lens Collected Post. @@ -29,7 +30,7 @@ contract LensCollectedPost is LensERC721, IERC7572 { constructor(address feed, uint256 postId, bool isImmutable) { LensERC721._initialize("Lens Collected Post", "LCP", ITokenURIProvider(address(0))); string memory contentURI = IFeed(feed).getPost(postId).contentURI; - require(bytes(contentURI).length > 0, "Post content URI is empty"); + require(bytes(contentURI).length > 0, Errors.InvalidParameter()); _feed = feed; _postId = postId; _contractURI = contentURI; @@ -41,7 +42,7 @@ contract LensCollectedPost is LensERC721, IERC7572 { } function mint(address to, uint256 tokenId) external { - require(msg.sender == _collectAction, "Only CollectAction can mint"); + require(msg.sender == _collectAction, Errors.InvalidMsgSender()); _mint(to, tokenId); } @@ -57,7 +58,7 @@ contract LensCollectedPost is LensERC721, IERC7572 { } else { string memory contentURI = IFeed(_feed).getPost(_postId).contentURI; // TODO: If content was deleted - should we fail or return empty string? - require(bytes(contentURI).length > 0); + require(bytes(contentURI).length > 0, Errors.DoesNotExist()); return contentURI; } } @@ -67,6 +68,6 @@ contract LensCollectedPost is LensERC721, IERC7572 { // Disabling integrated LensERC721 tokenURIProvider // TODO: Is this approach more favorable than deploying the LensCollectedPostTokenURIProvider over and over? function _beforeTokenURIProviderSet(ITokenURIProvider /* tokenURIProvider */ ) internal pure override { - revert(); + revert Errors.NotImplemented(); } } diff --git a/contracts/actions/post/collect/SimpleCollectAction.sol b/contracts/actions/post/collect/SimpleCollectAction.sol index f1a84551..8a6506f6 100644 --- a/contracts/actions/post/collect/SimpleCollectAction.sol +++ b/contracts/actions/post/collect/SimpleCollectAction.sol @@ -5,14 +5,13 @@ pragma solidity ^0.8.26; import {ISimpleCollectAction, CollectActionData} from "contracts/actions/post/collect/ISimpleCollectAction.sol"; import {IFeed} from "contracts/core/interfaces/IFeed.sol"; import {IGraph} from "contracts/core/interfaces/IGraph.sol"; - import {LensCollectedPost} from "contracts/actions/post/collect/LensCollectedPost.sol"; import {BasePostAction} from "contracts/actions/post/base/BasePostAction.sol"; - import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {MetadataBased} from "contracts/core/base/MetadataBased.sol"; import {KeyValue} from "contracts/core/types/Types.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; contract SimpleCollectAction is ISimpleCollectAction, BasePostAction, MetadataBased { using SafeERC20 for IERC20; @@ -107,7 +106,7 @@ contract SimpleCollectAction is ISimpleCollectAction, BasePostAction, MetadataBa // Editing existing collect action config if (storedData.isImmutable) { // TODO: Should we have two different bools? isImmutableConfig & isImmutableContentURI? - revert("Cannot edit immutable collect"); + revert Errors.Immutable(); } else { storedData.amount = configData.amount; storedData.collectLimit = configData.collectLimit; @@ -152,9 +151,9 @@ contract SimpleCollectAction is ISimpleCollectAction, BasePostAction, MetadataBa _validateSenderIsAuthor(originalMsgSender, feed, postId); CollectActionData storage storedData = $collectDataStorage().collectData[feed][postId]; // We don't check for existence of collect before disabling, because it might be useful to disable it initially - // require(storedData.collectionAddress != address(0), "Collect not configured for this post"); - require(!storedData.isImmutable, "Cannot modify immutable collect"); - require(storedData.isDisabled != isDisabled, "Already in desired state"); + // require(storedData.collectionAddress != address(0), Errors.DoesNotExist()); + require(!storedData.isImmutable, Errors.Immutable()); + require(storedData.isDisabled != isDisabled, Errors.RedundantStateChange()); storedData.isDisabled = isDisabled; return abi.encode(isDisabled); } @@ -165,18 +164,18 @@ contract SimpleCollectAction is ISimpleCollectAction, BasePostAction, MetadataBa function _validateSenderIsAuthor(address sender, address feed, uint256 postId) internal virtual { if (sender != IFeed(feed).getPostAuthor(postId)) { - revert("Sender is not the author"); + revert Errors.InvalidMsgSender(); } } function _validateConfigureParams(CollectActionConfigureParams memory configData) internal virtual { if (configData.amount == 0) { - require(configData.token == address(0), "Invalid token"); + require(configData.token == address(0), Errors.InvalidParameter()); } else { - require(configData.token != address(0), "Invalid token"); + require(configData.token != address(0), Errors.InvalidParameter()); } if (configData.endTimestamp != 0 && configData.endTimestamp < block.timestamp) { - revert("Invalid params"); + revert Errors.InvalidParameter(); } if (configData.followerOnlyGraph != address(0)) { // Check if the Graph supports isFollowing() interface with two random addresses @@ -209,24 +208,24 @@ contract SimpleCollectAction is ISimpleCollectAction, BasePostAction, MetadataBa ) internal virtual { CollectActionData storage data = $collectDataStorage().collectData[feed][postId]; - require(data.collectionAddress != address(0), "Collect not configured for this post"); + require(data.collectionAddress != address(0), Errors.DoesNotExist()); if (data.endTimestamp != 0 && block.timestamp > data.endTimestamp) { - revert("Collect expired"); + revert Errors.Expired(); } if (data.collectLimit != 0 && data.currentCollects + 1 > data.collectLimit) { - revert("Collect limit exceeded"); + revert Errors.LimitReached(); } if (expectedParams.amount != data.amount || expectedParams.token != data.token) { - revert("Invalid expected amount and/or token"); + revert Errors.InvalidParameter(); } if (data.followerOnlyGraph != address(0)) { require( IGraph(data.followerOnlyGraph).isFollowing(originalMsgSender, IFeed(feed).getPostAuthor(postId)), - "Not following" + Errors.NotFollowing() ); } @@ -236,12 +235,12 @@ contract SimpleCollectAction is ISimpleCollectAction, BasePostAction, MetadataBa require( keccak256(bytes(contentURI)) == keccak256(bytes(LensCollectedPost(data.collectionAddress).tokenURI(data.currentCollects))), - "Invalid content URI" + Errors.InvalidParameter() ); } if (data.isDisabled) { - revert("Collect is disabled"); + revert Errors.Disabled(); } } diff --git a/contracts/core/access/Ownable.sol b/contracts/core/access/Ownable.sol index d09e3418..1b2d6c33 100644 --- a/contracts/core/access/Ownable.sol +++ b/contracts/core/access/Ownable.sol @@ -2,6 +2,8 @@ // Copyright (C) 2024 Lens Labs. All Rights Reserved. pragma solidity ^0.8.26; +import {Errors} from "contracts/core/types/Errors.sol"; + abstract contract Ownable { event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); @@ -19,7 +21,7 @@ abstract contract Ownable { } modifier onlyOwner() { - require(msg.sender == $ownableStorage().owner); + require(msg.sender == $ownableStorage().owner, Errors.InvalidMsgSender()); _; } diff --git a/contracts/core/access/RoleBasedAccessControl.sol b/contracts/core/access/RoleBasedAccessControl.sol index dfa5ef75..b99b1eec 100644 --- a/contracts/core/access/RoleBasedAccessControl.sol +++ b/contracts/core/access/RoleBasedAccessControl.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.26; import {Access, IRoleBasedAccessControl} from "contracts/core/interfaces/IRoleBasedAccessControl.sol"; import {Events} from "contracts/core/types/Events.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; /** * This Access Control: @@ -40,7 +41,7 @@ contract RoleBasedAccessControl is IRoleBasedAccessControl { function transferOwnership(address newOwner) external virtual { address oldOwner = _owner; - require(msg.sender == oldOwner, "Only owner can transfer ownership"); + require(msg.sender == oldOwner, Errors.InvalidMsgSender()); _owner = newOwner; _revokeRole(oldOwner, OWNER_ROLE_ID); _grantRole(newOwner, OWNER_ROLE_ID); @@ -77,12 +78,12 @@ contract RoleBasedAccessControl is IRoleBasedAccessControl { } function _beforeGrantingRole(address, /* account */ uint256 roleId) internal virtual { - require(msg.sender == _owner, "Only owner can assign roles"); - require(roleId != OWNER_ROLE_ID, "Cannot grant owner role"); + require(msg.sender == _owner, Errors.InvalidMsgSender()); + require(roleId != OWNER_ROLE_ID, Errors.InvalidParameter()); } function _grantRole(address account, uint256 roleId) internal virtual { - require(!_hasRole(account, roleId)); + require(!_hasRole(account, roleId), Errors.RedundantStateChange()); _roles[account].push(roleId); emit Lens_AccessControl_RoleGranted(account, roleId); } @@ -93,13 +94,13 @@ contract RoleBasedAccessControl is IRoleBasedAccessControl { } function _beforeRevokingRole(address, /* account */ uint256 roleId) internal virtual { - require(msg.sender == _owner, "Only owner can revoke roles"); - require(roleId != OWNER_ROLE_ID, "Cannot revoke owner role"); + require(msg.sender == _owner, Errors.InvalidMsgSender()); + require(roleId != OWNER_ROLE_ID, Errors.InvalidParameter()); } function _revokeRole(address account, uint256 roleId) internal virtual { uint256 accountRolesLength = _roles[account].length; - require(accountRolesLength > 0); + require(accountRolesLength > 0, Errors.InvalidParameter()); uint256 roleIndex = 0; while (roleIndex < accountRolesLength) { if (_roles[account][roleIndex] == roleId) { @@ -108,7 +109,7 @@ contract RoleBasedAccessControl is IRoleBasedAccessControl { roleIndex++; } } - require(roleIndex < accountRolesLength); // Index must be found before reaching the end of the array + require(roleIndex < accountRolesLength, Errors.NotFound()); // Index must be found before reaching the end of the array _roles[account][roleIndex] = _roles[account][accountRolesLength - 1]; _roles[account].pop(); emit Lens_AccessControl_RoleRevoked(account, roleId); @@ -133,15 +134,15 @@ contract RoleBasedAccessControl is IRoleBasedAccessControl { uint256, /* permissionId */ Access /* access */ ) internal virtual { - require(msg.sender == _owner, "Only owner can set access"); - require(roleId != OWNER_ROLE_ID, "Cannot set access for owner role"); + require(msg.sender == _owner, Errors.InvalidMsgSender()); + require(roleId != OWNER_ROLE_ID, Errors.InvalidParameter()); } function _setAccess(uint256 roleId, address contractAddress, uint256 permissionId, Access access) internal virtual { Access perviousAccess = _access[roleId][contractAddress][permissionId]; _access[roleId][contractAddress][permissionId] = access; if (perviousAccess == Access.UNDEFINED) { - require(access != Access.UNDEFINED); + require(access != Access.UNDEFINED, Errors.RedundantStateChange()); emit Lens_AccessControl_AccessAdded(roleId, contractAddress, permissionId, access == Access.GRANTED); } else if (access == Access.UNDEFINED) { emit Lens_AccessControl_AccessRemoved(roleId, contractAddress, permissionId); @@ -171,8 +172,8 @@ contract RoleBasedAccessControl is IRoleBasedAccessControl { virtual returns (bool) { - require(contractAddress != ANY_CONTRACT_ADDRESS); - require(permissionId != ANY_PERMISSION_ID); + require(contractAddress != ANY_CONTRACT_ADDRESS, Errors.InvalidParameter()); + require(permissionId != ANY_PERMISSION_ID, Errors.InvalidParameter()); Access fullySpecifiedAccess = _access[roleId][contractAddress][permissionId]; diff --git a/contracts/core/base/BaseSource.sol b/contracts/core/base/BaseSource.sol index 84e398a8..410a2b77 100644 --- a/contracts/core/base/BaseSource.sol +++ b/contracts/core/base/BaseSource.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.26; import {ISource} from "contracts/core/interfaces/ISource.sol"; import {SourceStamp} from "contracts/core/types/Types.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; abstract contract BaseSource is ISource { bytes2 internal immutable EIP191_VERSION_BYTE_0X01_HEADER = 0x1901; @@ -21,9 +22,9 @@ abstract contract BaseSource is ISource { // Signature Standard: EIP-191 - Version Byte: 0x00 function _validateSource(SourceStamp calldata sourceStamp) internal virtual { - require(!_wasSourceStampNonceUsed[sourceStamp.nonce]); - require(sourceStamp.deadline >= block.timestamp); - require(sourceStamp.source == address(this)); + require(!_wasSourceStampNonceUsed[sourceStamp.nonce], Errors.NonceUsed()); + require(sourceStamp.deadline >= block.timestamp, Errors.Expired()); + require(sourceStamp.source == address(this), Errors.InvalidParameter()); _wasSourceStampNonceUsed[sourceStamp.nonce] = true; bytes32 digest = _calculateDigest(_calculateHashStruct(sourceStamp)); bytes32 r; @@ -36,7 +37,7 @@ abstract contract BaseSource is ISource { v := byte(0, mload(add(signature, 0x60))) } address signer = ecrecover(digest, v, r, s); - require(_isValidSourceStampSigner(signer)); + require(_isValidSourceStampSigner(signer), Errors.WrongSigner()); } function _isValidSourceStampSigner(address signer) internal virtual returns (bool); diff --git a/contracts/core/base/LensERC721.sol b/contracts/core/base/LensERC721.sol index a337c180..80ef8902 100644 --- a/contracts/core/base/LensERC721.sol +++ b/contracts/core/base/LensERC721.sol @@ -8,6 +8,7 @@ import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradea import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; import "contracts/core/interfaces/ITokenURIProvider.sol"; import "contracts/core/interfaces/IERC4906Events.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; abstract contract LensERC721 is IERC721 { using AddressUpgradeable for address; @@ -51,7 +52,7 @@ abstract contract LensERC721 is IERC721 { * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view virtual override returns (uint256) { - require(owner != address(0), "ERC721: address zero is not a valid owner"); + require(owner != address(0), Errors.InvalidParameter()); return $erc721Storage().balances[owner]; } @@ -60,7 +61,7 @@ abstract contract LensERC721 is IERC721 { */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { address owner = _ownerOf(tokenId); - require(owner != address(0), "ERC721: invalid token ID"); + require(owner != address(0), Errors.DoesNotExist()); return owner; } @@ -99,12 +100,9 @@ abstract contract LensERC721 is IERC721 { */ function approve(address to, uint256 tokenId) public virtual override { address owner = LensERC721.ownerOf(tokenId); - require(to != owner, "ERC721: approval to current owner"); + require(to != owner, Errors.InvalidParameter()); - require( - msg.sender == owner || isApprovedForAll(owner, msg.sender), - "ERC721: approve caller is not token owner or approved for all" - ); + require(msg.sender == owner || isApprovedForAll(owner, msg.sender), Errors.InvalidMsgSender()); _approve(to, tokenId); } @@ -137,7 +135,7 @@ abstract contract LensERC721 is IERC721 { */ function transferFrom(address from, address to, uint256 tokenId) public virtual override { //solhint-disable-next-line max-line-length - require(_isApprovedOrOwner(msg.sender, tokenId), "ERC721: caller is not token owner or approved"); + require(_isApprovedOrOwner(msg.sender, tokenId), Errors.InvalidMsgSender()); _transfer(from, to, tokenId); } @@ -153,7 +151,7 @@ abstract contract LensERC721 is IERC721 { * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual override { - require(_isApprovedOrOwner(msg.sender, tokenId), "ERC721: caller is not token owner or approved"); + require(_isApprovedOrOwner(msg.sender, tokenId), Errors.InvalidMsgSender()); _safeTransfer(from, to, tokenId, data); } @@ -177,7 +175,7 @@ abstract contract LensERC721 is IERC721 { */ function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual { _transfer(from, to, tokenId); - require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer"); + require(_checkOnERC721Received(from, to, tokenId, data), Errors.UnexpectedContractImpl()); } /** @@ -231,9 +229,7 @@ abstract contract LensERC721 is IERC721 { */ function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual { _mint(to, tokenId); - require( - _checkOnERC721Received(address(0), to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer" - ); + require(_checkOnERC721Received(address(0), to, tokenId, data), Errors.UnexpectedContractImpl()); } /** @@ -249,13 +245,13 @@ abstract contract LensERC721 is IERC721 { * Emits a {Transfer} event. */ function _mint(address to, uint256 tokenId) internal virtual { - require(to != address(0), "ERC721: mint to the zero address"); - require(!_exists(tokenId), "ERC721: token already minted"); + require(to != address(0), Errors.InvalidParameter()); + require(!_exists(tokenId), Errors.AlreadyExists()); _beforeTokenTransfer(address(0), to, tokenId); // Check that tokenId was not minted by `_beforeTokenTransfer` hook - require(!_exists(tokenId), "ERC721: token already minted"); + require(!_exists(tokenId), Errors.AlreadyExists()); unchecked { // Will not overflow unless all 2**256 token ids are minted to the same owner. @@ -318,13 +314,13 @@ abstract contract LensERC721 is IERC721 { * Emits a {Transfer} event. */ function _transfer(address from, address to, uint256 tokenId) internal virtual { - require(LensERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); - require(to != address(0), "ERC721: transfer to the zero address"); + require(LensERC721.ownerOf(tokenId) == from, Errors.InvalidParameter()); + require(to != address(0), Errors.InvalidParameter()); _beforeTokenTransfer(from, to, tokenId); // Check that tokenId was not transferred by `_beforeTokenTransfer` hook - require(LensERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); + require(LensERC721.ownerOf(tokenId) == from, Errors.InvalidParameter()); // Clear approvals from the previous owner delete $erc721Storage().tokenApprovals[tokenId]; @@ -361,7 +357,7 @@ abstract contract LensERC721 is IERC721 { * Emits an {ApprovalForAll} event. */ function _setApprovalForAll(address owner, address operator, bool approved) internal virtual { - require(owner != operator, "ERC721: approve to caller"); + require(owner != operator, Errors.InvalidParameter()); $erc721Storage().operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } @@ -370,7 +366,7 @@ abstract contract LensERC721 is IERC721 { * @dev Reverts if the `tokenId` has not been minted yet. */ function _requireMinted(uint256 tokenId) internal view virtual { - require(_exists(tokenId), "ERC721: invalid token ID"); + require(_exists(tokenId), Errors.DoesNotExist()); } /** @@ -393,7 +389,7 @@ abstract contract LensERC721 is IERC721 { return retval == IERC721ReceiverUpgradeable.onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { - revert("ERC721: transfer to non ERC721Receiver implementer"); + revert Errors.UnexpectedContractImpl(); } else { /// @solidity memory-safe-assembly assembly { diff --git a/contracts/core/base/MetadataBased.sol b/contracts/core/base/MetadataBased.sol index 523652fe..085fea8f 100644 --- a/contracts/core/base/MetadataBased.sol +++ b/contracts/core/base/MetadataBased.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.26; import {IMetadataBased} from "contracts/core/interfaces/IMetadataBased.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; abstract contract MetadataBased is IMetadataBased { struct MetadataURIStorage { @@ -33,7 +34,7 @@ abstract contract MetadataBased is IMetadataBased { } function _beforeMetadataURIUpdate(string memory /* metadataURI */ ) internal virtual { - revert(); + revert Errors.NotImplemented(); } function _emitMetadataURISet(string memory /* metadataURI */ ) internal virtual; diff --git a/contracts/core/base/RuleBasedPrimitive.sol b/contracts/core/base/RuleBasedPrimitive.sol index 6a81fc55..0a7478ec 100644 --- a/contracts/core/base/RuleBasedPrimitive.sol +++ b/contracts/core/base/RuleBasedPrimitive.sol @@ -12,6 +12,7 @@ import { KeyValue } from "contracts/core/types/Types.sol"; import {CallLib} from "contracts/core/libraries/CallLib.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; abstract contract RuleBasedPrimitive { using RulesLib for RulesStorage; @@ -203,7 +204,7 @@ abstract contract RuleBasedPrimitive { return; } } - revert(); + revert Errors.UnsupportedSelector(); } function _beforeChangeRules(uint256 entityId, RuleChange[] calldata ruleChanges) internal virtual { @@ -228,8 +229,8 @@ abstract contract RuleBasedPrimitive { bytes4 ruleSelector = selectorsToValidate[i]; uint256 requiredRulesLength = rulesStorage._getRulesArray(ruleSelector, true).length; uint256 anyOfRulesLength = rulesStorage._getRulesArray(ruleSelector, false).length; - require(anyOfRulesLength != 1, "Cannot have exactly one single any-of rule"); - require(requiredRulesLength + anyOfRulesLength <= RulesLib.MAX_AMOUNT_OF_RULES, "Amount of rules exceeded"); + require(anyOfRulesLength != 1, Errors.SingleAnyOfRule()); + require(requiredRulesLength + anyOfRulesLength <= RulesLib.MAX_AMOUNT_OF_RULES, Errors.LimitReached()); } } diff --git a/contracts/core/libraries/AccessControlLib.sol b/contracts/core/libraries/AccessControlLib.sol index e204c52a..08d9d7ec 100644 --- a/contracts/core/libraries/AccessControlLib.sol +++ b/contracts/core/libraries/AccessControlLib.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.26; import {IAccessControl} from "contracts/core/interfaces/IAccessControl.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; library AccessControlLib { function requireAccess(address accessControl, address account, uint256 permissionId) internal view { @@ -10,7 +11,10 @@ library AccessControlLib { } function requireAccess(IAccessControl accessControl, address account, uint256 permissionId) internal view { - require(accessControl.hasAccess({account: account, contractAddress: address(this), permissionId: permissionId})); + require( + accessControl.hasAccess({account: account, contractAddress: address(this), permissionId: permissionId}), + Errors.AccessDenied() + ); } function hasAccess(address accessControl, address account, uint256 permissionId) internal view returns (bool) { @@ -38,6 +42,9 @@ library AccessControlLib { } function requireCanChangeAccessControl(IAccessControl accessControl, address account) internal view { - require(accessControl.canChangeAccessControl({account: account, contractAddress: address(this)})); + require( + accessControl.canChangeAccessControl({account: account, contractAddress: address(this)}), + Errors.AccessDenied() + ); } } diff --git a/contracts/core/libraries/CallLib.sol b/contracts/core/libraries/CallLib.sol index 1b6b0e26..a808cb8b 100644 --- a/contracts/core/libraries/CallLib.sol +++ b/contracts/core/libraries/CallLib.sol @@ -2,11 +2,13 @@ // Copyright (C) 2024 Lens Labs. All Rights Reserved. pragma solidity ^0.8.26; +import {Errors} from "contracts/core/types/Errors.sol"; + library CallLib { function safecall(address target, bytes memory data) internal returns (bool, bytes memory) { (bool success, bytes memory returnData) = target.call(data); if (success) { - require(returnData.length != 0 || target.code.length != 0, "NOT_A_CONTRACT"); + require(returnData.length != 0 || target.code.length != 0, Errors.NotAContract()); } return (success, returnData); } @@ -14,7 +16,7 @@ library CallLib { function safecall(address target, uint256 value, bytes memory data) internal returns (bool, bytes memory) { (bool success, bytes memory returnData) = target.call{value: value}(data); if (success) { - require(returnData.length != 0 || target.code.length != 0, "NOT_A_CONTRACT"); + require(returnData.length != 0 || target.code.length != 0, Errors.NotAContract()); } return (success, returnData); } diff --git a/contracts/core/libraries/RulesLib.sol b/contracts/core/libraries/RulesLib.sol index 991ddcba..82d16d94 100644 --- a/contracts/core/libraries/RulesLib.sol +++ b/contracts/core/libraries/RulesLib.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.26; import {Rule} from "contracts/core/types/Types.sol"; import {CallLib} from "contracts/core/libraries/CallLib.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; struct RulesStorage { mapping(bytes4 => Rule[]) requiredRules; @@ -32,7 +33,7 @@ library RulesLib { if (providedConfigSalt == 0x00) { return bytes32(++rulesStorage.lastConfigSaltGenerated); } else { - require(rulesStorage.isConfigured[ruleAddress][providedConfigSalt]); + require(rulesStorage.isConfigured[ruleAddress][providedConfigSalt], Errors.InvalidConfigSalt()); return providedConfigSalt; } } @@ -46,7 +47,7 @@ library RulesLib { bool wasAlreadyConfigured = rulesStorage.isConfigured[ruleAddress][configSalt]; rulesStorage.isConfigured[ruleAddress][configSalt] = true; (bool success,) = ruleAddress.safecall(encodedConfigureCall); - require(success); + require(success, Errors.ConfigureCallReverted()); return wasAlreadyConfigured; } @@ -57,8 +58,11 @@ library RulesLib { bytes32 configSalt, bytes4 ruleSelector ) internal { - require(rulesStorage.isConfigured[ruleAddress][configSalt]); - require(!_isSelectorAlreadyEnabled(rulesStorage, ruleSelector, ruleAddress, configSalt)); + require(rulesStorage.isConfigured[ruleAddress][configSalt], Errors.RuleNotConfigured()); + require( + !_isSelectorAlreadyEnabled(rulesStorage, ruleSelector, ruleAddress, configSalt), + Errors.RedundantStateChange() + ); _addRuleSelectorToStorage(rulesStorage, ruleSelector, ruleAddress, configSalt, isRequired); } @@ -69,7 +73,9 @@ library RulesLib { bytes32 configSalt, bytes4 ruleSelector ) internal { - require(_isSelectorAlreadyEnabled(rulesStorage, ruleSelector, ruleAddress, configSalt)); + require( + _isSelectorAlreadyEnabled(rulesStorage, ruleSelector, ruleAddress, configSalt), Errors.RedundantStateChange() + ); _removeRuleSelectorFromStorage(rulesStorage, ruleSelector, ruleAddress, configSalt); } diff --git a/contracts/core/primitives/feed/Feed.sol b/contracts/core/primitives/feed/Feed.sol index 140501c3..357ac54a 100644 --- a/contracts/core/primitives/feed/Feed.sol +++ b/contracts/core/primitives/feed/Feed.sol @@ -13,6 +13,7 @@ import {Events} from "contracts/core/types/Events.sol"; import {SourceStampBased} from "contracts/core/base/SourceStampBased.sol"; import {MetadataBased} from "contracts/core/base/MetadataBased.sol"; import {Initializable} from "contracts/core/upgradeability/Initializable.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; contract Feed is IFeed, @@ -77,7 +78,7 @@ contract Feed is virtual override { - require(msg.sender == Core.$storage().posts[entityId].author); + require(msg.sender == Core.$storage().posts[entityId].author, Errors.InvalidMsgSender()); } // Public user functions @@ -89,7 +90,7 @@ contract Feed is RuleProcessingParams[] calldata rootPostRulesParams, RuleProcessingParams[] calldata quotedPostRulesParams ) external virtual override returns (uint256) { - require(msg.sender == postParams.author, "MSG_SENDER_NOT_AUTHOR"); + require(msg.sender == postParams.author, Errors.InvalidMsgSender()); (uint256 postId, uint256 authorPostSequentialId, uint256 rootPostId) = Core._createPost(postParams); address source = _processSourceStamp(postId, customParams); _setPrimitiveInternalExtraDataForEntity(postId, KeyValue(DATA__LAST_UPDATED_SOURCE, abi.encode(source))); @@ -103,7 +104,7 @@ contract Feed is } } if (postId != rootPostId) { - require(postParams.ruleChanges.length == 0, "ONLY_ROOT_POSTS_CAN_HAVE_RULES"); + require(postParams.ruleChanges.length == 0, Errors.CannotHaveRules()); // This covers the Reply or Repost cases _processPostCreationOnRootPost(rootPostId, postId, postParams, customParams, rootPostRulesParams); } else { @@ -141,7 +142,7 @@ contract Feed is address author = Core.$storage().posts[postId].author; // TODO: We can have this for moderators: // require(msg.sender == author || _hasAccess(msg.sender, EDIT_POST_PID)); - require(msg.sender == author, "MSG_SENDER_NOT_AUTHOR"); + require(msg.sender == author, Errors.InvalidMsgSender()); bool[] memory wereExtraDataValuesSet = new bool[](postParams.extraData.length); for (uint256 i = 0; i < postParams.extraData.length; i++) { @@ -186,7 +187,7 @@ contract Feed is RuleProcessingParams[] calldata feedRulesParams ) external virtual override { address author = Core.$storage().posts[postId].author; - require(msg.sender == author || _hasAccess(msg.sender, PID__REMOVE_POST), "MSG_SENDER_NOT_AUTHOR_NOR_HAS_ACCESS"); + require(msg.sender == author || _hasAccess(msg.sender, PID__REMOVE_POST), Errors.InvalidMsgSender()); Core._removePost(postId); _processPostRemoval(postId, customParams, feedRulesParams); address source = _processSourceStamp(postId, customParams); @@ -215,7 +216,7 @@ contract Feed is // Getters function getPost(uint256 postId) external view override returns (Post memory) { - require(Core._postExists(postId), "POST_DOES_NOT_EXIST"); + require(Core._postExists(postId), Errors.DoesNotExist()); return Post({ author: Core.$storage().posts[postId].author, authorPostSequentialId: Core.$storage().posts[postId].authorPostSequentialId, @@ -237,7 +238,7 @@ contract Feed is } function getPostAuthor(uint256 postId) external view override returns (address) { - require(Core._postExists(postId), "POST_DOES_NOT_EXIST"); + require(Core._postExists(postId), Errors.DoesNotExist()); return Core.$storage().posts[postId].author; } @@ -250,7 +251,7 @@ contract Feed is } function getPostExtraData(uint256 postId, bytes32 key) external view override returns (bytes memory) { - require(Core._postExists(postId), "POST_DOES_NOT_EXIST"); + require(Core._postExists(postId), Errors.DoesNotExist()); address postAuthor = Core.$storage().posts[postId].author; return _getEntityExtraData(postAuthor, postId, key); } @@ -260,12 +261,12 @@ contract Feed is } function getPostSequentialId(uint256 postId) external view override returns (uint256) { - require(Core._postExists(postId), "POST_DOES_NOT_EXIST"); + require(Core._postExists(postId), Errors.DoesNotExist()); return Core.$storage().posts[postId].postSequentialId; } function getAuthorPostSequentialId(uint256 postId) external view override returns (uint256) { - require(Core._postExists(postId), "POST_DOES_NOT_EXIST"); + require(Core._postExists(postId), Errors.DoesNotExist()); return Core.$storage().posts[postId].authorPostSequentialId; } diff --git a/contracts/core/primitives/feed/FeedCore.sol b/contracts/core/primitives/feed/FeedCore.sol index 2e193320..2eee2cc6 100644 --- a/contracts/core/primitives/feed/FeedCore.sol +++ b/contracts/core/primitives/feed/FeedCore.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.26; import {EditPostParams, CreatePostParams} from "contracts/core/interfaces/IFeed.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; struct PostStorage { address author; @@ -52,22 +53,20 @@ library FeedCore { _newPost.contentURI = postParams.contentURI; uint256 rootPostId = postId; if (postParams.quotedPostId != 0) { - require(_postExists(postParams.quotedPostId), "QUOTED_POST_DOES_NOT_EXIST"); + require(_postExists(postParams.quotedPostId), Errors.DoesNotExist()); _newPost.quotedPostId = postParams.quotedPostId; } if (postParams.repliedPostId != 0) { - require(_postExists(postParams.repliedPostId), "REPLIED_POST_DOES_NOT_EXIST"); + require(_postExists(postParams.repliedPostId), Errors.DoesNotExist()); _newPost.repliedPostId = postParams.repliedPostId; rootPostId = $storage().posts[postParams.repliedPostId].rootPostId; } if (postParams.repostedPostId != 0) { - require(_postExists(postParams.repostedPostId), "REPOSTED_POST_DOES_NOT_EXIST"); + require(_postExists(postParams.repostedPostId), Errors.DoesNotExist()); _newPost.repostedPostId = postParams.repostedPostId; rootPostId = $storage().posts[postParams.repostedPostId].rootPostId; - require( - postParams.quotedPostId == 0 && postParams.repliedPostId == 0, "REPOST_CANNOT_HAVE_QUOTED_OR_REPLIED" - ); - require(bytes(postParams.contentURI).length == 0, "REPOST_CANNOT_HAVE_CONTENT"); + require(postParams.quotedPostId == 0 && postParams.repliedPostId == 0, Errors.InvalidParameter()); + require(bytes(postParams.contentURI).length == 0, Errors.InvalidParameter()); } _newPost.rootPostId = rootPostId; _newPost.creationTimestamp = uint80(block.timestamp); @@ -77,9 +76,9 @@ library FeedCore { function _editPost(uint256 postId, EditPostParams calldata postParams) internal { PostStorage storage _post = $storage().posts[postId]; - require(_post.creationTimestamp != 0, "CANNOT_EDIT_NON_EXISTENT_POST"); // Post must exist + require(_post.creationTimestamp != 0, Errors.DoesNotExist()); // Post must exist if (_post.repostedPostId != 0) { - require(bytes(postParams.contentURI).length == 0, "REPOST_CANNOT_HAVE_CONTENT"); + require(bytes(postParams.contentURI).length == 0, Errors.InvalidParameter()); } else { _post.contentURI = postParams.contentURI; } diff --git a/contracts/core/primitives/feed/RuleBasedFeed.sol b/contracts/core/primitives/feed/RuleBasedFeed.sol index 35a58b55..d6967577 100644 --- a/contracts/core/primitives/feed/RuleBasedFeed.sol +++ b/contracts/core/primitives/feed/RuleBasedFeed.sol @@ -10,6 +10,7 @@ import {RuleProcessingParams, Rule, RuleChange, KeyValue} from "contracts/core/t import {EditPostParams, CreatePostParams} from "contracts/core/interfaces/IFeed.sol"; import {RuleBasedPrimitive} from "contracts/core/base/RuleBasedPrimitive.sol"; import {CallLib} from "contracts/core/libraries/CallLib.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { using RulesLib for RulesStorage; @@ -192,7 +193,7 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { (bool callNotReverted,) = encodeAndCall( rule.ruleAddress, rule.configSalt, rootPostId, postId, postParams, customParams, ruleCustomParams ); - require(callNotReverted, "Some required rule failed"); + require(callNotReverted, Errors.RequiredRuleReverted()); } } // Check any-of rules (OR-combined rules) @@ -215,7 +216,7 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { } } // If there are any-of rules and it reached this point, it means all of them failed. - require(_rulesStorage.anyOfRules[ruleSelector].length == 0, "All of the any-of rules failed"); + require(_rulesStorage.anyOfRules[ruleSelector].length == 0, Errors.AllAnyOfRulesReverted()); } function _processPostCreationOnRootPost( @@ -346,7 +347,7 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { (bool callNotReverted,) = encodeAndCall( rule.ruleAddress, rule.configSalt, rootPostId, postId, postParams, customParams, ruleCustomParams ); - require(callNotReverted, "Some required rule failed"); + require(callNotReverted, Errors.RequiredRuleReverted()); } } // Check any-of rules (OR-combined rules) @@ -369,7 +370,7 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { } } // If there are any-of rules and it reached this point, it means all of them failed. - require(_rulesStorage.anyOfRules[ruleSelector].length == 0, "All of the any-of rules failed"); + require(_rulesStorage.anyOfRules[ruleSelector].length == 0, Errors.AllAnyOfRulesReverted()); } function _processPostRemoval( @@ -394,7 +395,7 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { IFeedRule.processRemovePost, (rule.configSalt, postId, customParams, ruleCustomParams) ) ); - require(callNotReverted, "Some required rule failed"); + require(callNotReverted, Errors.RequiredRuleReverted()); } } // Check any-of rules (OR-combined rules) @@ -419,7 +420,7 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { } } // If there are any-of rules and it reached this point, it means all of them failed. - require($feedRulesStorage().anyOfRules[ruleSelector].length == 0, "All of the any-of rules failed"); + require($feedRulesStorage().anyOfRules[ruleSelector].length == 0, Errors.AllAnyOfRulesReverted()); } function _processPostRulesChanges( @@ -444,7 +445,7 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { IFeedRule.processPostRuleChanges, (rule.configSalt, postId, ruleChanges, ruleCustomParams) ) ); - require(callNotReverted, "Some required rule failed"); + require(callNotReverted, Errors.RequiredRuleReverted()); } } // Check any-of rules (OR-combined rules) @@ -469,6 +470,6 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { } } // If there are any-of rules and it reached this point, it means all of them failed. - require($feedRulesStorage().anyOfRules[ruleSelector].length == 0, "All of the any-of rules failed"); + require($feedRulesStorage().anyOfRules[ruleSelector].length == 0, Errors.AllAnyOfRulesReverted()); } } diff --git a/contracts/core/primitives/graph/Graph.sol b/contracts/core/primitives/graph/Graph.sol index 5ae74183..ab16d57f 100644 --- a/contracts/core/primitives/graph/Graph.sol +++ b/contracts/core/primitives/graph/Graph.sol @@ -13,6 +13,7 @@ import {Events} from "contracts/core/types/Events.sol"; import {SourceStampBased} from "contracts/core/base/SourceStampBased.sol"; import {MetadataBased} from "contracts/core/base/MetadataBased.sol"; import {Initializable} from "contracts/core/upgradeability/Initializable.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; contract Graph is IGraph, @@ -73,7 +74,7 @@ contract Graph is virtual override { - require(msg.sender == address(uint160(entityId))); // Follow rules can only be changed in your own account + require(msg.sender == address(uint160(entityId)), Errors.InvalidMsgSender()); // Follow rules can only be changed in your own account } function setExtraData(KeyValue[] calldata extraDataToSet) external override { @@ -105,7 +106,7 @@ contract Graph is RuleProcessingParams[] calldata followRulesProcessingParams, KeyValue[] calldata extraData ) external virtual override returns (uint256) { - require(msg.sender == followerAccount); + require(msg.sender == followerAccount, Errors.InvalidMsgSender()); // followId is now in customParams - think if we want to implement this now, or later. For now passing 0 always. uint256 assignedFollowId = Core._follow(followerAccount, accountToFollow, 0, block.timestamp); address source = _processSourceStamp(assignedFollowId, customParams); @@ -130,7 +131,7 @@ contract Graph is KeyValue[] calldata customParams, RuleProcessingParams[] calldata graphRulesProcessingParams ) external virtual override returns (uint256) { - require(msg.sender == followerAccount); + require(msg.sender == followerAccount, Errors.InvalidMsgSender()); uint256 followId = Core._unfollow(followerAccount, accountToUnfollow); address source = _processSourceStamp(followId, customParams); _graphProcessUnfollow(msg.sender, followerAccount, accountToUnfollow, customParams, graphRulesProcessingParams); @@ -148,13 +149,13 @@ contract Graph is function getFollowerById(address account, uint256 followId) external view override returns (address) { address follower = Core.$storage().followers[account][followId]; - require(follower != address(0), "FOLLOWER_DOES_NOT_EXIST"); + require(follower != address(0), Errors.DoesNotExist()); return follower; } function getFollow(address followerAccount, address targetAccount) external view override returns (Follow memory) { Follow memory followData = Core.$storage().follows[followerAccount][targetAccount]; - require(followData.id != 0, "FOLLOW_DOES_NOT_EXIST"); + require(followData.id != 0, Errors.DoesNotExist()); return followData; } diff --git a/contracts/core/primitives/graph/GraphCore.sol b/contracts/core/primitives/graph/GraphCore.sol index 6840f613..fb0292fc 100644 --- a/contracts/core/primitives/graph/GraphCore.sol +++ b/contracts/core/primitives/graph/GraphCore.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.26; import {Follow} from "contracts/core/interfaces/IGraph.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; library GraphCore { // Storage @@ -30,13 +31,13 @@ library GraphCore { internal returns (uint256) { - require(followerAccount != accountToFollow); // Cannot follow yourself - require($storage().follows[followerAccount][accountToFollow].id == 0); // Cannot follow more than once + require(followerAccount != accountToFollow, Errors.Self()); + require($storage().follows[followerAccount][accountToFollow].id == 0, Errors.CannotFollowAgain()); if (followId == 0) { followId = ++$storage().lastFollowIdAssigned[accountToFollow]; } else { - require(followId < $storage().lastFollowIdAssigned[accountToFollow]); // Only previous Follow IDs allowed to be reused - require($storage().followers[accountToFollow][followId] == address(0)); // Follow ID is already taken + require(followId < $storage().lastFollowIdAssigned[accountToFollow], Errors.InvalidParameter()); // Only previous Follow IDs allowed to be reused + require($storage().followers[accountToFollow][followId] == address(0), Errors.AlreadyExists()); // Follow ID is already taken } $storage().follows[followerAccount][accountToFollow] = Follow({id: followId, timestamp: timestamp}); $storage().followers[accountToFollow][followId] = followerAccount; @@ -47,7 +48,7 @@ library GraphCore { function _unfollow(address followerAccount, address accountToUnfollow) internal returns (uint256) { uint256 followId = $storage().follows[followerAccount][accountToUnfollow].id; - require(followId != 0); // Must be following + require(followId != 0, Errors.NotFollowing()); // Must be following $storage().followersCount[accountToUnfollow]--; $storage().followingCount[followerAccount]--; delete $storage().followers[accountToUnfollow][followId]; diff --git a/contracts/core/primitives/graph/RuleBasedGraph.sol b/contracts/core/primitives/graph/RuleBasedGraph.sol index 71838d92..36a94ba3 100644 --- a/contracts/core/primitives/graph/RuleBasedGraph.sol +++ b/contracts/core/primitives/graph/RuleBasedGraph.sol @@ -9,6 +9,7 @@ import {RuleProcessingParams, RuleChange, Rule, KeyValue} from "contracts/core/t import {IGraph} from "contracts/core/interfaces/IGraph.sol"; import {RuleBasedPrimitive} from "contracts/core/base/RuleBasedPrimitive.sol"; import {CallLib} from "contracts/core/libraries/CallLib.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive { using RulesLib for RulesStorage; @@ -151,7 +152,7 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive { IGraphRule.processFollowRuleChanges, (rule.configSalt, account, ruleChanges, ruleCustomParams) ) ); - require(callNotReverted, "Some required rule failed"); + require(callNotReverted, Errors.RequiredRuleReverted()); } } // Check any-of rules (OR-combined rules) @@ -176,7 +177,7 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive { } } // If there are any-of rules and it reached this point, it means all of them failed. - require($graphRulesStorage().anyOfRules[ruleSelector].length == 0, "All of the any-of rules failed"); + require($graphRulesStorage().anyOfRules[ruleSelector].length == 0, Errors.AllAnyOfRulesReverted()); } function _encodeAndCallGraphProcessFollow( @@ -339,7 +340,7 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive { primitiveCustomParams, ruleCustomParams ); - require(callNotReverted, "Some required rule failed"); + require(callNotReverted, Errors.RequiredRuleReverted()); } } for (uint256 i = 0; i < rulesStorage.anyOfRules[ruleSelector].length; i++) { @@ -367,7 +368,7 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive { } } // If there are any-of rules and it reached this point, it means all of them failed. - require($graphRulesStorage().anyOfRules[ruleSelector].length == 0, "All of the any-of rules failed"); + require($graphRulesStorage().anyOfRules[ruleSelector].length == 0, Errors.AllAnyOfRulesReverted()); } function _processFollow( @@ -402,7 +403,7 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive { primitiveCustomParams, ruleCustomParams ); - require(callNotReverted, "Some required rule failed"); + require(callNotReverted, Errors.RequiredRuleReverted()); } } for (uint256 i = 0; i < rulesStorage.anyOfRules[ruleSelector].length; i++) { @@ -430,6 +431,6 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive { } } // If there are any-of rules and it reached this point, it means all of them failed. - require($graphRulesStorage().anyOfRules[ruleSelector].length == 0, "All of the any-of rules failed"); + require($graphRulesStorage().anyOfRules[ruleSelector].length == 0, Errors.AllAnyOfRulesReverted()); } } diff --git a/contracts/core/primitives/group/Group.sol b/contracts/core/primitives/group/Group.sol index 49ea88d7..c9f79dd5 100644 --- a/contracts/core/primitives/group/Group.sol +++ b/contracts/core/primitives/group/Group.sol @@ -14,6 +14,7 @@ import {IGroupRule} from "contracts/core/interfaces/IGroupRule.sol"; import {SourceStampBased} from "contracts/core/base/SourceStampBased.sol"; import {MetadataBased} from "contracts/core/base/MetadataBased.sol"; import {Initializable} from "contracts/core/upgradeability/Initializable.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; contract Group is IGroup, @@ -127,7 +128,7 @@ contract Group is KeyValue[] calldata customParams, RuleProcessingParams[] calldata ruleProcessingParams ) external override { - require(msg.sender == account); + require(msg.sender == account, Errors.InvalidMsgSender()); uint256 membershipId = Core._grantMembership(account); _processMemberJoining(msg.sender, account, customParams, ruleProcessingParams); address source = _processSourceStamp(membershipId, customParams); @@ -139,7 +140,7 @@ contract Group is KeyValue[] calldata customParams, RuleProcessingParams[] calldata ruleProcessingParams ) external override { - require(msg.sender == account); + require(msg.sender == account, Errors.InvalidMsgSender()); uint256 membershipId = Core._revokeMembership(account); _processMemberLeaving(msg.sender, account, customParams, ruleProcessingParams); address source = _processSourceStamp(membershipId, customParams); @@ -158,19 +159,19 @@ contract Group is function getMembership(address account) external view override returns (Membership memory) { Membership memory membership = Core._getMembership(account); - require(membership.id != 0, "NOT_A_MEMBER"); + require(membership.id != 0, Errors.DoesNotExist()); return membership; } function getMembershipTimestamp(address account) external view override returns (uint256) { Membership memory membership = Core._getMembership(account); - require(membership.id != 0, "NOT_A_MEMBER"); + require(membership.id != 0, Errors.DoesNotExist()); return membership.timestamp; } function getMembershipId(address account) external view override returns (uint256) { uint256 membershipId = Core.$storage().memberships[account].id; - require(membershipId != 0, "NOT_A_MEMBER"); + require(membershipId != 0, Errors.DoesNotExist()); return membershipId; } diff --git a/contracts/core/primitives/group/GroupCore.sol b/contracts/core/primitives/group/GroupCore.sol index 0fee6e0b..2a58b2f3 100644 --- a/contracts/core/primitives/group/GroupCore.sol +++ b/contracts/core/primitives/group/GroupCore.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.26; import {Membership} from "contracts/core/interfaces/IGroup.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; library GroupCore { // Storage @@ -35,14 +36,14 @@ library GroupCore { function _grantMembership(address account) internal returns (uint256) { uint256 membershipId = ++$storage().lastMemberIdAssigned; $storage().numberOfMembers++; - require($storage().memberships[account].id == 0); // Must not be a member yet + require($storage().memberships[account].id == 0, Errors.RedundantStateChange()); // Must not be a member yet $storage().memberships[account] = Membership(membershipId, block.timestamp); return membershipId; } function _revokeMembership(address account) internal returns (uint256) { uint256 membershipId = $storage().memberships[account].id; - require(membershipId != 0); // Must be a member + require(membershipId != 0, Errors.RedundantStateChange()); // Must be a member $storage().numberOfMembers--; delete $storage().memberships[account]; return membershipId; diff --git a/contracts/core/primitives/group/RuleBasedGroup.sol b/contracts/core/primitives/group/RuleBasedGroup.sol index a251710e..05e25622 100644 --- a/contracts/core/primitives/group/RuleBasedGroup.sol +++ b/contracts/core/primitives/group/RuleBasedGroup.sol @@ -8,6 +8,7 @@ import {RulesStorage, RulesLib} from "contracts/core/libraries/RulesLib.sol"; import {RuleChange, RuleProcessingParams, Rule, KeyValue} from "contracts/core/types/Types.sol"; import {RuleBasedPrimitive} from "contracts/core/base/RuleBasedPrimitive.sol"; import {CallLib} from "contracts/core/libraries/CallLib.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; abstract contract RuleBasedGroup is IGroup, RuleBasedPrimitive { using RulesLib for RulesStorage; @@ -243,7 +244,7 @@ abstract contract RuleBasedGroup is IGroup, RuleBasedPrimitive { (bool callNotReverted,) = encodeAndCall( rule.ruleAddress, rule.configSalt, originalMsgSender, account, primitiveCustomParams, ruleParams ); - require(callNotReverted, "Some required rule failed"); + require(callNotReverted, Errors.RequiredRuleReverted()); } } // Check any-of rules (OR-combined rules) @@ -266,6 +267,6 @@ abstract contract RuleBasedGroup is IGroup, RuleBasedPrimitive { } } // If there are any-of rules and it reached this point, it means all of them failed. - require($groupRulesStorage().anyOfRules[ruleSelector].length == 0, "All of the any-of rules failed"); + require($groupRulesStorage().anyOfRules[ruleSelector].length == 0, Errors.AllAnyOfRulesReverted()); } } diff --git a/contracts/core/primitives/namespace/Namespace.sol b/contracts/core/primitives/namespace/Namespace.sol index d1e6e928..67ce98df 100644 --- a/contracts/core/primitives/namespace/Namespace.sol +++ b/contracts/core/primitives/namespace/Namespace.sol @@ -16,6 +16,7 @@ import {ITokenURIProvider} from "contracts/core/interfaces/ITokenURIProvider.sol import {SourceStampBased} from "contracts/core/base/SourceStampBased.sol"; import {MetadataBased} from "contracts/core/base/MetadataBased.sol"; import {Initializable} from "contracts/core/upgradeability/Initializable.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; contract Namespace is INamespace, @@ -102,7 +103,7 @@ contract Namespace is RuleProcessingParams[] calldata assigningProcessingParams, KeyValue[] memory extraData ) external { - require(msg.sender == account); // msg.sender must be the account + require(msg.sender == account, Errors.InvalidMsgSender()); uint256 id = _computeId(username); _safeMint(account, id); _idToUsername[id] = username; @@ -124,7 +125,7 @@ contract Namespace is RuleProcessingParams[] calldata ruleProcessingParams, KeyValue[] calldata extraData ) external override { - require(msg.sender == account); // msg.sender must be the account + require(msg.sender == account, Errors.InvalidMsgSender()); uint256 id = _computeId(username); _safeMint(account, id); _idToUsername[id] = username; @@ -143,7 +144,7 @@ contract Namespace is ) external override { uint256 id = _computeId(username); address owner = _ownerOf(id); - require(msg.sender == owner); // msg.sender must be the owner of the username + require(msg.sender == owner, Errors.InvalidMsgSender()); // msg.sender must be the owner of the username _processRemoval(msg.sender, username, customParams, removalRuleProcessingParams); address source = _processSourceStamp(id, customParams); _unassignIfAssigned(username, customParams, unassigningRuleProcessingParams, source); @@ -160,9 +161,9 @@ contract Namespace is RuleProcessingParams[] calldata unassignUsernameRuleProcessingParams, RuleProcessingParams[] calldata assignRuleProcessingParams ) external override { - require(msg.sender == account); // msg.sender must be the account + require(msg.sender == account, Errors.InvalidMsgSender()); uint256 id = _computeId(username); - require(account == _ownerOf(id)); // account should own the tokenized username + require(account == _ownerOf(id), Errors.InvalidMsgSender()); // account should own the tokenized username address source = _processSourceStamp(id, customParams); _unassignIfAssigned(account, customParams, unassignAccountRuleProcessingParams, source); _unassignIfAssigned(username, customParams, unassignUsernameRuleProcessingParams, source); @@ -178,7 +179,7 @@ contract Namespace is ) external override { address account = Core.$storage().usernameToAccount[username]; uint256 id = _computeId(username); - require(msg.sender == account || msg.sender == _ownerOf(id)); + require(msg.sender == account || msg.sender == _ownerOf(id), Errors.InvalidMsgSender()); Core._unassignUsername(username); _processUnassigning(msg.sender, account, username, customParams, ruleProcessingParams); address source = _processSourceStamp(id, customParams); @@ -209,7 +210,7 @@ contract Namespace is function setUsernameExtraData(string calldata username, KeyValue[] calldata extraDataToSet) external { uint256 id = _computeId(username); address owner = _ownerOf(id); - require(msg.sender == owner); + require(msg.sender == owner, Errors.InvalidMsgSender()); _decodeAndSetUsernameExtraData(id, extraDataToSet); } @@ -275,13 +276,13 @@ contract Namespace is function usernameOf(address user) external view returns (string memory) { string memory username = Core.$storage().accountToUsername[user]; - require(bytes(username).length != 0, "NO_USERNAME_ASSIGNED"); + require(bytes(username).length != 0, Errors.DoesNotExist()); return username; } function accountOf(string memory username) external view returns (address) { uint256 tokenId = _computeId(username); - require(_exists(tokenId), "NO_SUCH_USERNAME"); + require(_exists(tokenId), Errors.DoesNotExist()); return Core.$storage().usernameToAccount[username]; } diff --git a/contracts/core/primitives/namespace/NamespaceCore.sol b/contracts/core/primitives/namespace/NamespaceCore.sol index 6b6403da..9570312e 100644 --- a/contracts/core/primitives/namespace/NamespaceCore.sol +++ b/contracts/core/primitives/namespace/NamespaceCore.sol @@ -2,6 +2,8 @@ // Copyright (C) 2024 Lens Labs. All Rights Reserved. pragma solidity ^0.8.26; +import {Errors} from "contracts/core/types/Errors.sol"; + library NamespaceCore { // Storage @@ -42,28 +44,28 @@ library NamespaceCore { // Internal functions - Use these functions to be called as an inlined library function _createUsername(string memory username) internal { - require(!$storage().usernameExists[username]); // Username must not exist yet - require(bytes(username).length > 0); // Username must not be empty + require(!$storage().usernameExists[username], Errors.AlreadyExists()); // Username must not exist yet + require(bytes(username).length > 0, Errors.InvalidParameter()); // Username must not be empty $storage().usernameExists[username] = true; } function _removeUsername(string memory username) internal { - require($storage().usernameExists[username]); // Username must exist - require($storage().usernameToAccount[username] == address(0)); // Username must not be assigned + require($storage().usernameExists[username], Errors.DoesNotExist()); // Username must exist + require($storage().usernameToAccount[username] == address(0), Errors.UsernameAssigned()); // Username must not be assigned $storage().usernameExists[username] = false; } function _assignUsername(address account, string memory username) internal { - require($storage().usernameExists[username]); // Username must exist - require($storage().usernameToAccount[username] == address(0)); // Username must not be assigned yet - require(bytes($storage().accountToUsername[account]).length == 0); // Account must not have a username yet + require($storage().usernameExists[username], Errors.DoesNotExist()); // Username must exist + require($storage().usernameToAccount[username] == address(0), Errors.UsernameAssigned()); // Username must not be assigned yet + require(bytes($storage().accountToUsername[account]).length == 0, Errors.UsernameAssigned()); // Account must not have a username yet $storage().usernameToAccount[username] = account; $storage().accountToUsername[account] = username; } function _unassignUsername(string memory username) internal { address account = $storage().usernameToAccount[username]; - require(account != address(0)); // Username must be assigned + require(account != address(0), Errors.RedundantStateChange()); // Username must be assigned delete $storage().accountToUsername[account]; delete $storage().usernameToAccount[username]; } diff --git a/contracts/core/primitives/namespace/RuleBasedNamespace.sol b/contracts/core/primitives/namespace/RuleBasedNamespace.sol index 7af1eaa5..6aaa08ba 100644 --- a/contracts/core/primitives/namespace/RuleBasedNamespace.sol +++ b/contracts/core/primitives/namespace/RuleBasedNamespace.sol @@ -8,6 +8,7 @@ import {RuleChange, RuleProcessingParams, Rule, KeyValue} from "contracts/core/t import {INamespace} from "contracts/core/interfaces/INamespace.sol"; import {RuleBasedPrimitive} from "contracts/core/base/RuleBasedPrimitive.sol"; import {CallLib} from "contracts/core/libraries/CallLib.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; abstract contract RuleBasedNamespace is INamespace, RuleBasedPrimitive { using RulesLib for RulesStorage; @@ -267,7 +268,7 @@ abstract contract RuleBasedNamespace is INamespace, RuleBasedPrimitive { primitiveCustomParams, ruleParams ); - require(callNotReverted, "Some required rule failed"); + require(callNotReverted, Errors.RequiredRuleReverted()); } } // Check any-of rules (OR-combined rules) @@ -296,6 +297,6 @@ abstract contract RuleBasedNamespace is INamespace, RuleBasedPrimitive { } } // If there are any-of rules and it reached this point, it means all of them failed. - require($namespaceRulesStorage().anyOfRules[ruleSelector].length == 0, "All of the any-of rules failed"); + require($namespaceRulesStorage().anyOfRules[ruleSelector].length == 0, Errors.AllAnyOfRulesReverted()); } } diff --git a/contracts/core/types/Errors.sol b/contracts/core/types/Errors.sol new file mode 100644 index 00000000..94651071 --- /dev/null +++ b/contracts/core/types/Errors.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: UNLICENSED +// Copyright (C) 2024 Lens Labs. All Rights Reserved. +pragma solidity ^0.8.26; + +library Errors { + error AccessDenied(); + error AllAnyOfRulesReverted(); + error AlreadyExists(); + error AlreadyInitialized(); + error AutoUpgradeEnabled(); + error Banned(); + error Blocked(); + error CannotFollowAgain(); + error CannotHaveRules(); + error CannotStartWithThat(); + error ConfigureCallReverted(); + error Disabled(); + error DoesNotExist(); + error DuplicatedValue(); + error Expired(); + error Immutable(); + error InvalidConfigSalt(); + error InvalidMsgSender(); + error InvalidParameter(); + error InvalidSignature(); + error LimitReached(); + error Locked(); + error NonceUsed(); + error NotAContract(); + error NotAllowed(); + error NotAMember(); + error NotEnough(); + error NotFollowing(); + error NotFound(); + error NotImplemented(); + error RedundantStateChange(); + error RequiredRuleReverted(); + error RuleNotConfigured(); + error Self(); + error SingleAnyOfRule(); + error UnexpectedContractImpl(); + error UnsupportedSelector(); + error Untrusted(); + error UsernameAssigned(); + error WrongSigner(); +} diff --git a/contracts/core/upgradeability/Beacon.sol b/contracts/core/upgradeability/Beacon.sol index 00114db2..39619f31 100644 --- a/contracts/core/upgradeability/Beacon.sol +++ b/contracts/core/upgradeability/Beacon.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.26; import {Ownable} from "contracts/core/access/Ownable.sol"; import {IVersionedBeacon} from "contracts/core/interfaces/IVersionedBeacon.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; contract Beacon is Ownable, IVersionedBeacon { event ImplementationSetForVersion(uint256 indexed version, address indexed implementation); @@ -14,7 +15,7 @@ contract Beacon is Ownable, IVersionedBeacon { constructor(address owner, uint256 version, address initialImplementation) Ownable() { _transferOwnership(owner); - require(initialImplementation != address(0)); + require(initialImplementation != address(0), Errors.InvalidParameter()); _implementations[version] = initialImplementation; emit ImplementationSetForVersion(version, initialImplementation); _defaultVersion = version; @@ -27,20 +28,20 @@ contract Beacon is Ownable, IVersionedBeacon { function implementation(uint256 implementationVersion) external view override returns (address) { address implementationByVersion = _implementations[implementationVersion]; - require(implementationByVersion != address(0)); + require(implementationByVersion != address(0), Errors.InvalidParameter()); return implementationByVersion; } function setImplementationForVersion(uint256 version, address implementationToSet) external onlyOwner { if (_defaultVersion == version) { - require(implementationToSet != address(0)); + require(implementationToSet != address(0), Errors.InvalidParameter()); } _implementations[version] = implementationToSet; emit ImplementationSetForVersion(version, implementationToSet); } function setDefaultVersion(uint256 version) external onlyOwner { - require(_implementations[version] != address(0)); + require(_implementations[version] != address(0), Errors.InvalidParameter()); _defaultVersion = version; emit DefaultVersionSet(version); } diff --git a/contracts/core/upgradeability/BeaconProxy.sol b/contracts/core/upgradeability/BeaconProxy.sol index 64e91ad7..d11a2b92 100644 --- a/contracts/core/upgradeability/BeaconProxy.sol +++ b/contracts/core/upgradeability/BeaconProxy.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.26; import {IVersionedBeacon} from "contracts/core/interfaces/IVersionedBeacon.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; contract BeaconProxy { event Upgraded(address indexed implementation); @@ -62,27 +63,27 @@ contract BeaconProxy { } function changeProxyAdmin(address proxyAdmin) external { - require(msg.sender == $proxyAdmin().value); + require(msg.sender == $proxyAdmin().value, Errors.InvalidMsgSender()); $proxyAdmin().value = proxyAdmin; emit AdminChanged(msg.sender, proxyAdmin); } function optOutFromAutoUpgrade() external { - require(msg.sender == $proxyAdmin().value); + require(msg.sender == $proxyAdmin().value, Errors.InvalidMsgSender()); $autoUpgrade().value = false; emit AutoUpgradeChanged(false); } function optInToAutoUpgrade() external { - require(msg.sender == $proxyAdmin().value); + require(msg.sender == $proxyAdmin().value, Errors.InvalidMsgSender()); $autoUpgrade().value = true; emit AutoUpgradeChanged(true); _fetchImplFromBeaconAndAutoUpgradeIfNeeded(); } function setImplementation(address implementation) external { - require(msg.sender == $proxyAdmin().value); - require($autoUpgrade().value == false); + require(msg.sender == $proxyAdmin().value, Errors.InvalidMsgSender()); + require($autoUpgrade().value == false, Errors.AutoUpgradeEnabled()); if (implementation != $implementation().value) { $implementation().value = implementation; emit Upgraded(implementation); @@ -90,7 +91,7 @@ contract BeaconProxy { } function setBeacon(address beacon) external { - require(msg.sender == $proxyAdmin().value); + require(msg.sender == $proxyAdmin().value, Errors.InvalidMsgSender()); if (beacon != $beacon().value) { $beacon().value = beacon; emit BeaconUpgraded(beacon); @@ -101,7 +102,7 @@ contract BeaconProxy { } function triggerUpgradeToVersion(uint256 implementationVersion) external { - require(msg.sender == $proxyAdmin().value); + require(msg.sender == $proxyAdmin().value, Errors.InvalidMsgSender()); address implementationFromBeacon = IVersionedBeacon($beacon().value).implementation(implementationVersion); if (implementationFromBeacon != $implementation().value) { emit Upgraded(implementationFromBeacon); @@ -110,7 +111,7 @@ contract BeaconProxy { } function triggerUpgrade() external { - require(msg.sender == $proxyAdmin().value); + require(msg.sender == $proxyAdmin().value, Errors.InvalidMsgSender()); _fetchImplFromBeaconAndAutoUpgradeIfNeeded(); } diff --git a/contracts/core/upgradeability/Initializable.sol b/contracts/core/upgradeability/Initializable.sol index ab1f658d..dd9e0f71 100644 --- a/contracts/core/upgradeability/Initializable.sol +++ b/contracts/core/upgradeability/Initializable.sol @@ -2,6 +2,8 @@ // Copyright (C) 2024 Lens Labs. All Rights Reserved. pragma solidity ^0.8.26; +import {Errors} from "contracts/core/types/Errors.sol"; + abstract contract Initializable { // Storage @@ -19,7 +21,7 @@ abstract contract Initializable { } modifier initializer() { - require(!$initializableStorage().initialized, "ALREADY_INITIALIZED"); + require(!$initializableStorage().initialized, Errors.AlreadyInitialized()); $initializableStorage().initialized = true; _; } diff --git a/contracts/core/upgradeability/ProxyAdmin.sol b/contracts/core/upgradeability/ProxyAdmin.sol index a6dbc587..56a038b3 100644 --- a/contracts/core/upgradeability/ProxyAdmin.sol +++ b/contracts/core/upgradeability/ProxyAdmin.sol @@ -6,6 +6,7 @@ import {ILock} from "contracts/core/interfaces/ILock.sol"; import {BeaconProxy} from "contracts/core/upgradeability/BeaconProxy.sol"; import {Ownable} from "contracts/core/access/Ownable.sol"; import {CallLib} from "contracts/core/libraries/CallLib.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; contract ProxyAdmin is Ownable { using CallLib for address; @@ -23,18 +24,18 @@ contract ProxyAdmin is Ownable { if (LOCK.isLocked()) { // While the Proxy Admin is locked it: // - Cannot change Proxy Admin in the Proxy, only in the ProxyAdmin contract itself - require(selector != BeaconProxy.changeProxyAdmin.selector); + require(selector != BeaconProxy.changeProxyAdmin.selector, Errors.Locked()); // - Cannot change the Beacon in the Proxy - require(selector != BeaconProxy.setBeacon.selector); + require(selector != BeaconProxy.setBeacon.selector, Errors.Locked()); // - Cannot change the implementation in the Proxy - require(selector != BeaconProxy.setImplementation.selector); + require(selector != BeaconProxy.setImplementation.selector, Errors.Locked()); // - Cannot trigger an upgrade in the Proxy - require(selector != BeaconProxy.triggerUpgradeToVersion.selector); - require(selector != BeaconProxy.triggerUpgrade.selector); + require(selector != BeaconProxy.triggerUpgradeToVersion.selector, Errors.Locked()); + require(selector != BeaconProxy.triggerUpgrade.selector, Errors.Locked()); // - Cannot opt-out from auto-upgrade in the Proxy - require(selector != BeaconProxy.optOutFromAutoUpgrade.selector); + require(selector != BeaconProxy.optOutFromAutoUpgrade.selector, Errors.Locked()); // - Cannot opt-in to auto-upgrade in the Proxy - require(selector != BeaconProxy.optInToAutoUpgrade.selector); + require(selector != BeaconProxy.optInToAutoUpgrade.selector, Errors.Locked()); } // Do the call (bool success, bytes memory ret) = to.safecall(value, data); diff --git a/contracts/extensions/access/OwnerAdminOnlyAccessControl.sol b/contracts/extensions/access/OwnerAdminOnlyAccessControl.sol index d0129823..c02e0fda 100644 --- a/contracts/extensions/access/OwnerAdminOnlyAccessControl.sol +++ b/contracts/extensions/access/OwnerAdminOnlyAccessControl.sol @@ -5,6 +5,7 @@ pragma solidity ^0.8.26; import {Events} from "contracts/core/types/Events.sol"; import {RoleBasedAccessControl} from "contracts/core/access/RoleBasedAccessControl.sol"; import {Access} from "contracts/core/interfaces/IRoleBasedAccessControl.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; contract OwnerAdminOnlyAccessControl is RoleBasedAccessControl { /// @custom:keccak lens.role.Admin @@ -17,7 +18,7 @@ contract OwnerAdminOnlyAccessControl is RoleBasedAccessControl { } function _beforeGrantingRole(address account, uint256 roleId) internal virtual override { - require(roleId == ADMIN_ROLE_ID, "You cannot grant other roles than ADMIN"); + require(roleId == ADMIN_ROLE_ID, Errors.InvalidParameter()); super._beforeGrantingRole(account, roleId); } @@ -27,7 +28,7 @@ contract OwnerAdminOnlyAccessControl is RoleBasedAccessControl { uint256, /*permissionId*/ Access /*access*/ ) internal virtual override { - revert(); + revert Errors.NotImplemented(); } function getType() external pure virtual override returns (bytes32) { diff --git a/contracts/extensions/account/Account.sol b/contracts/extensions/account/Account.sol index 3d2ddc48..0c1bcff8 100644 --- a/contracts/extensions/account/Account.sol +++ b/contracts/extensions/account/Account.sol @@ -12,6 +12,7 @@ import {ISource} from "contracts/core/interfaces/ISource.sol"; import {ExtraStorageBased} from "contracts/core/base/ExtraStorageBased.sol"; import {MetadataBased} from "contracts/core/base/MetadataBased.sol"; import {Initializable} from "contracts/core/upgradeability/Initializable.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; contract Account is IAccount, Initializable, Ownable, IERC721Receiver, ExtraStorageBased, MetadataBased { // TODO: Think how long the timelock should be and should it be configurable @@ -74,9 +75,7 @@ contract Account is IAccount, Initializable, Ownable, IERC721Receiver, ExtraStor // TODO: Should we replace setMetadataURI with extraData? Cause here it looks like _setPrimitiveExtraDataByUser case function setMetadataURI(string calldata metadataURI, SourceStamp calldata sourceStamp) external override { if (msg.sender != owner()) { - require( - $storage().accountManagerPermissions[msg.sender].canSetMetadataURI, "No permissions to set metadata URI" - ); + require($storage().accountManagerPermissions[msg.sender].canSetMetadataURI, Errors.NotAllowed()); } if (sourceStamp.source != address(0)) { ISource(sourceStamp.source).validateSource(sourceStamp); @@ -92,10 +91,10 @@ contract Account is IAccount, Initializable, Ownable, IERC721Receiver, ExtraStor function allowNonOwnerSpending(bool allow) external onlyOwner { if (allow) { - require($storage().allowNonOwnerSpendingTimestamp == 0, "Non-Owner Spending Already Allowed"); + require($storage().allowNonOwnerSpendingTimestamp == 0, Errors.RedundantStateChange()); $storage().allowNonOwnerSpendingTimestamp = block.timestamp; } else { - require($storage().allowNonOwnerSpendingTimestamp > 0, "Non-Owner Spending Already Not Allowed"); + require($storage().allowNonOwnerSpendingTimestamp > 0, Errors.RedundantStateChange()); delete $storage().allowNonOwnerSpendingTimestamp; } emit Lens_Account_AllowNonOwnerSpending(allow, allow ? block.timestamp : 0); @@ -107,18 +106,17 @@ contract Account is IAccount, Initializable, Ownable, IERC721Receiver, ExtraStor onlyOwner { require( - !$storage().accountManagerPermissions[accountManager].canExecuteTransactions, - "Account manager already exists" + !$storage().accountManagerPermissions[accountManager].canExecuteTransactions, Errors.RedundantStateChange() ); - require(accountManager != owner(), "Cannot add owner as account manager"); - require(accountManager != address(0), "Cannot add zero address as account manager"); + require(accountManager != owner(), Errors.InvalidParameter()); + require(accountManager != address(0), Errors.InvalidParameter()); $storage().accountManagerPermissions[accountManager] = accountManagerPermissions; emit Lens_Account_AccountManagerAdded(accountManager, accountManagerPermissions); } function removeAccountManager(address accountManager) external override onlyOwner { require( - $storage().accountManagerPermissions[accountManager].canExecuteTransactions, "Account manager already exists" + $storage().accountManagerPermissions[accountManager].canExecuteTransactions, Errors.RedundantStateChange() ); delete $storage().accountManagerPermissions[accountManager]; emit Lens_Account_AccountManagerRemoved(accountManager); @@ -128,10 +126,8 @@ contract Account is IAccount, Initializable, Ownable, IERC721Receiver, ExtraStor address accountManager, AccountManagerPermissions calldata accountManagerPermissions ) external override onlyOwner { - require( - $storage().accountManagerPermissions[accountManager].canExecuteTransactions, "Account manager does not exist" - ); - require(accountManagerPermissions.canExecuteTransactions, "Cannot remove execution permissions"); + require($storage().accountManagerPermissions[accountManager].canExecuteTransactions, Errors.InvalidParameter()); + require(accountManagerPermissions.canExecuteTransactions, Errors.InvalidParameter()); $storage().accountManagerPermissions[accountManager] = accountManagerPermissions; emit Lens_Account_AccountManagerUpdated(accountManager, accountManagerPermissions); } @@ -147,26 +143,17 @@ contract Account is IAccount, Initializable, Ownable, IERC721Receiver, ExtraStor returns (bytes memory) { if (msg.sender != owner()) { - require( - $storage().accountManagerPermissions[msg.sender].canExecuteTransactions, - "No permissions to execute transactions" - ); + require($storage().accountManagerPermissions[msg.sender].canExecuteTransactions, Errors.NotAllowed()); if (value > 0) { - require( - $storage().accountManagerPermissions[msg.sender].canTransferNative, - "No permissions to transfer native tokens" - ); + require($storage().accountManagerPermissions[msg.sender].canTransferNative, Errors.NotAllowed()); } if (_isTransferRelatedSelector(bytes4(data[:4]))) { require( $storage().allowNonOwnerSpendingTimestamp > 0 && block.timestamp - $storage().allowNonOwnerSpendingTimestamp > SPENDING_TIMELOCK, - "Spender Lock ON: Non-owner spending not allowed" - ); - require( - $storage().accountManagerPermissions[msg.sender].canTransferTokens, - "No permissions to transfer tokens" + Errors.NotAllowed() ); + require($storage().accountManagerPermissions[msg.sender].canTransferTokens, Errors.NotAllowed()); } } (bool success, bytes memory ret) = to.call{value: value}(data); diff --git a/contracts/extensions/actions/ActionHub.sol b/contracts/extensions/actions/ActionHub.sol index 24706a13..229441a8 100644 --- a/contracts/extensions/actions/ActionHub.sol +++ b/contracts/extensions/actions/ActionHub.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.26; import {KeyValue} from "contracts/core/types/Types.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; interface IPostAction { function configure(address originalMsgSender, address feed, uint256 postId, KeyValue[] calldata params) @@ -98,7 +99,7 @@ contract ActionHub { function signalUniversalPostAction(address action) external { bytes memory returnData = IPostAction(action).configure(address(0), address(0), 0, new KeyValue[](0)); - require(abi.decode(returnData, (bytes32)) == UNIVERSAL_ACTION_MAGIC_VALUE); + require(abi.decode(returnData, (bytes32)) == UNIVERSAL_ACTION_MAGIC_VALUE, Errors.UnexpectedContractImpl()); emit Lens_ActionHub_PostAction_Universal(action); } @@ -144,7 +145,7 @@ contract ActionHub { function signalUniversalAccountAction(address action) external { bytes memory returnData = IAccountAction(action).configure(address(0), address(0), new KeyValue[](0)); - require(abi.decode(returnData, (bytes32)) == UNIVERSAL_ACTION_MAGIC_VALUE); + require(abi.decode(returnData, (bytes32)) == UNIVERSAL_ACTION_MAGIC_VALUE, Errors.UnexpectedContractImpl()); emit Lens_ActionHub_AccountAction_Universal(action); } diff --git a/contracts/extensions/factories/LensFactory.sol b/contracts/extensions/factories/LensFactory.sol index f20da6da..33ed6e71 100644 --- a/contracts/extensions/factories/LensFactory.sol +++ b/contracts/extensions/factories/LensFactory.sol @@ -31,6 +31,7 @@ import {IGraphRule} from "contracts/core/interfaces/IGraphRule.sol"; import {PARAM__GROUP} from "contracts/rules/feed/GroupGatedFeedRule.sol"; import {AccessControlled} from "contracts/core/access/AccessControlled.sol"; import {IGroup} from "contracts/core/interfaces/IGroup.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; // TODO: Move this some place else or remove interface IOwnable { @@ -180,8 +181,8 @@ contract LensFactory { IRoleBasedAccessControl feedAccessControl = _deployAccessControl(owner, admins); for (uint256 i = 0; i < feedRules.length; i++) { - require(feedRules[i].ruleAddress != ACCOUNT_BLOCKING_RULE, "ACCOUNT_BLOCKING_RULE WAS ALREADY PREPENDED"); - require(feedRules[i].ruleAddress != GROUP_GATED_FEED_RULE, "GroupGatedRule was already prepended"); + require(feedRules[i].ruleAddress != ACCOUNT_BLOCKING_RULE, Errors.DuplicatedValue()); + require(feedRules[i].ruleAddress != GROUP_GATED_FEED_RULE, Errors.DuplicatedValue()); modifiedFeedRules[i + 2] = _injectRuleAccessControl(feedRules[i], address(feedAccessControl)); } @@ -311,9 +312,9 @@ contract LensFactory { if (rule.configurationChanges.configure) { for (uint256 i = 0; i < rule.configurationChanges.ruleParams.length; i++) { if (rule.configurationChanges.ruleParams[i].key == PARAM__ACCESS_CONTROL) { - require(!found); + require(!found, Errors.DuplicatedValue()); found = true; - require(rule.configurationChanges.ruleParams[i].value.length == 0); + require(rule.configurationChanges.ruleParams[i].value.length == 0, Errors.InvalidParameter()); rule.configurationChanges.ruleParams[i].value = abi.encode(accessControl); } } @@ -348,7 +349,7 @@ contract LensFactory { selectorChanges: selectorChanges }); for (uint256 i = 0; i < rules.length; i++) { - require(rules[i].ruleAddress != ACCOUNT_BLOCKING_RULE, "ACCOUNT_BLOCKING_RULE WAS ALREADY PREPENDED"); + require(rules[i].ruleAddress != ACCOUNT_BLOCKING_RULE, Errors.DuplicatedValue()); modifiedRules[i + 1] = _injectRuleAccessControl(rules[i], accessControl); } return modifiedRules; diff --git a/contracts/extensions/primitives/app/AppCore.sol b/contracts/extensions/primitives/app/AppCore.sol index 2f7db9cc..8d8e5755 100644 --- a/contracts/extensions/primitives/app/AppCore.sol +++ b/contracts/extensions/primitives/app/AppCore.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.26; import "contracts/core/libraries/ExtraDataLib.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; struct ArrayStorageHelper { uint8 index; @@ -50,8 +51,8 @@ library AppCore { function _add(address element, address[] storage array, mapping(address => ArrayStorageHelper) storage arrayHelper) internal { - require(element != address(0), "INVALID_ELEMENT"); - require(!arrayHelper[element].isSet, "ALREADY_ADDED"); + require(element != address(0), Errors.InvalidParameter()); + require(!arrayHelper[element].isSet, Errors.RedundantStateChange()); array.push(element); arrayHelper[element] = ArrayStorageHelper({index: uint8(array.length - 1), isSet: true}); } @@ -61,7 +62,7 @@ library AppCore { address[] storage array, mapping(address => ArrayStorageHelper) storage arrayHelper ) internal { - require(arrayHelper[element].isSet, "NOT_FOUND"); + require(arrayHelper[element].isSet, Errors.NotFound()); uint256 index = arrayHelper[element].index; array[index] = array[array.length - 1]; arrayHelper[array[index]].index = uint8(index); @@ -83,7 +84,7 @@ library AppCore { bool wasAValuePreviouslySet = $storage().defaultGraph != address(0); if (graph != address(0)) { // address(0) allowed as a way to remove the default graph - require($storage().graphStorageHelper[graph].isSet, "NOT_FOUND"); + require($storage().graphStorageHelper[graph].isSet, Errors.NotFound()); } $storage().defaultGraph = graph; return wasAValuePreviouslySet; @@ -103,7 +104,7 @@ library AppCore { bool wasAValuePreviouslySet = $storage().defaultFeed != address(0); if (feed != address(0)) { // address(0) allowed as a way to remove the default feed - require($storage().feedStorageHelper[feed].isSet, "NOT_FOUND"); + require($storage().feedStorageHelper[feed].isSet, Errors.NotFound()); } $storage().defaultFeed = feed; return wasAValuePreviouslySet; @@ -127,7 +128,7 @@ library AppCore { bool wasAValuePreviouslySet = $storage().defaultNamespace != address(0); if (namespace != address(0)) { // address(0) allowed as a way to remove the default namespace - require($storage().namespaceStorageHelper[namespace].isSet, "NOT_FOUND"); + require($storage().namespaceStorageHelper[namespace].isSet, Errors.NotFound()); } $storage().defaultNamespace = namespace; return wasAValuePreviouslySet; @@ -146,7 +147,7 @@ library AppCore { function _setDefaultGroup(address group) internal { if (group != address(0)) { // address(0) allowed as a way to remove the default group - require($storage().groupStorageHelper[group].isSet, "NOT_FOUND"); + require($storage().groupStorageHelper[group].isSet, Errors.NotFound()); } $storage().defaultGroup = group; } @@ -165,7 +166,7 @@ library AppCore { bool wasAValuePreviouslySet = $storage().defaultPaymaster != address(0); if (paymaster != address(0)) { // address(0) allowed as a way to remove the default paymaster - require($storage().paymasterStorageHelper[paymaster].isSet, "NOT_FOUND"); + require($storage().paymasterStorageHelper[paymaster].isSet, Errors.NotFound()); } $storage().defaultPaymaster = paymaster; return wasAValuePreviouslySet; diff --git a/contracts/migration/MigrationFeed.sol b/contracts/migration/MigrationFeed.sol index 234655b7..f469e4f3 100644 --- a/contracts/migration/MigrationFeed.sol +++ b/contracts/migration/MigrationFeed.sol @@ -6,6 +6,7 @@ import {KeyValue, RuleProcessingParams} from "contracts/core/types/Types.sol"; import {CreatePostParams} from "contracts/core/interfaces/IFeed.sol"; import {FeedCore as Core, PostStorage} from "contracts/core/primitives/feed/FeedCore.sol"; import {Feed} from "contracts/core/primitives/feed/Feed.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; contract MigrationFeed is Feed { function createPost( @@ -85,20 +86,20 @@ contract MigrationFeed is Feed { function _forceChecks(uint256 postId, uint256 rootPostId, CreatePostParams calldata postParams) internal view { // TODO: Check if the rootPostId == postId case (not a reply, not a repost) if (rootPostId != postId) { - require(Core._postExists(rootPostId)); + require(Core._postExists(rootPostId), Errors.DoesNotExist()); } if (postParams.quotedPostId != 0) { - require(Core._postExists(postParams.quotedPostId)); + require(Core._postExists(postParams.quotedPostId), Errors.DoesNotExist()); } if (postParams.repliedPostId != 0) { - require(Core._postExists(postParams.repliedPostId)); - require(rootPostId == Core.$storage().posts[postParams.repliedPostId].rootPostId); + require(Core._postExists(postParams.repliedPostId), Errors.DoesNotExist()); + require(rootPostId == Core.$storage().posts[postParams.repliedPostId].rootPostId, Errors.InvalidParameter()); } if (postParams.repostedPostId != 0) { - require(Core._postExists(postParams.repostedPostId)); - require(postParams.quotedPostId == 0 && postParams.repliedPostId == 0); - require(rootPostId == Core.$storage().posts[postParams.repostedPostId].rootPostId); - require(bytes(postParams.contentURI).length == 0, "REPOST_CANNOT_HAVE_CONTENT"); + require(Core._postExists(postParams.repostedPostId), Errors.DoesNotExist()); + require(postParams.quotedPostId == 0 && postParams.repliedPostId == 0, Errors.InvalidParameter()); + require(rootPostId == Core.$storage().posts[postParams.repostedPostId].rootPostId, Errors.InvalidParameter()); + require(bytes(postParams.contentURI).length == 0, Errors.InvalidParameter()); } } } diff --git a/contracts/rules/base/AccountBlockingRule.sol b/contracts/rules/base/AccountBlockingRule.sol index f4bb4744..7c3a3280 100644 --- a/contracts/rules/base/AccountBlockingRule.sol +++ b/contracts/rules/base/AccountBlockingRule.sol @@ -8,6 +8,7 @@ import {CreatePostParams, EditPostParams} from "contracts/core/interfaces/IFeed. import {KeyValue, RuleChange} from "contracts/core/types/Types.sol"; import {IFeed} from "contracts/core/interfaces/IFeed.sol"; import {MetadataBased} from "contracts/core/base/MetadataBased.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; contract AccountBlockingRule is IFeedRule, IGraphRule, MetadataBased { event Lens_AccountBlocking_AccountBlocked(address indexed source, address indexed target, uint256 timestamp); @@ -32,13 +33,13 @@ contract AccountBlockingRule is IFeedRule, IGraphRule, MetadataBased { {} function blockUser(address source, address target) external { - require(msg.sender == source, "Only the source can block a user"); - require(source != target, "Cannot block self"); + require(msg.sender == source, Errors.InvalidMsgSender()); + require(source != target, Errors.Self()); accountBlocks[source][target] = block.timestamp; } function unblockUser(address source, address target) external { - require(msg.sender == source, "Only the source can unblock a user"); + require(msg.sender == source, Errors.InvalidMsgSender()); accountBlocks[msg.sender][target] = 0; } @@ -55,10 +56,10 @@ contract AccountBlockingRule is IFeedRule, IGraphRule, MetadataBased { uint256 rootPostId = IFeed(msg.sender).getPost(postId).rootPostId; address rootAuthor = IFeed(msg.sender).getPostAuthor(rootPostId); if (_isBlocked({source: repliedToAuthor, blockTarget: author})) { - revert("User is blocked from replying to this user"); + revert Errors.Blocked(); } if (_isBlocked({source: rootAuthor, blockTarget: author})) { - revert("User is blocked from commenting on this author's posts"); + revert Errors.Blocked(); } } } @@ -72,7 +73,7 @@ contract AccountBlockingRule is IFeedRule, IGraphRule, MetadataBased { KeyValue[] calldata /* ruleExecutionParams */ ) external view { if (_isBlocked({source: accountToFollow, blockTarget: followerAccount})) { - revert("User is blocked from following this user"); + revert Errors.Blocked(); } } @@ -93,7 +94,7 @@ contract AccountBlockingRule is IFeedRule, IGraphRule, MetadataBased { KeyValue[] calldata, /* primitiveCustomParams */ KeyValue[] calldata /* ruleExecutionParams */ ) external pure { - revert(); + revert Errors.NotImplemented(); } function processRemovePost( @@ -102,7 +103,7 @@ contract AccountBlockingRule is IFeedRule, IGraphRule, MetadataBased { KeyValue[] calldata, /* primitiveCustomParams */ KeyValue[] calldata /* ruleExecutionParams */ ) external pure { - revert(); + revert Errors.NotImplemented(); } function processPostRuleChanges( @@ -111,7 +112,7 @@ contract AccountBlockingRule is IFeedRule, IGraphRule, MetadataBased { RuleChange[] calldata, /* ruleChanges */ KeyValue[] calldata /* ruleExecutionParams */ ) external pure { - revert(); + revert Errors.NotImplemented(); } function processUnfollow( @@ -122,7 +123,7 @@ contract AccountBlockingRule is IFeedRule, IGraphRule, MetadataBased { KeyValue[] calldata, /* primitiveCustomParams */ KeyValue[] calldata /* ruleExecutionParams */ ) external pure { - revert(); + revert Errors.NotImplemented(); } function processFollowRuleChanges( @@ -131,6 +132,6 @@ contract AccountBlockingRule is IFeedRule, IGraphRule, MetadataBased { RuleChange[] calldata, /* ruleChanges */ KeyValue[] calldata /* ruleExecutionParams */ ) external pure { - revert(); + revert Errors.NotImplemented(); } } diff --git a/contracts/rules/base/RestrictedSignersRule.sol b/contracts/rules/base/RestrictedSignersRule.sol index 443834e9..349f2aed 100644 --- a/contracts/rules/base/RestrictedSignersRule.sol +++ b/contracts/rules/base/RestrictedSignersRule.sol @@ -6,8 +6,9 @@ import {EIP712EncodingLib} from "contracts/core/libraries/EIP712EncodingLib.sol" import {IERC1271} from "@openzeppelin/contracts/interfaces/IERC1271.sol"; import {KeyValue} from "contracts/core/types/Types.sol"; import {MetadataBased} from "contracts/core/base/MetadataBased.sol"; -// Move to types +import {Errors} from "contracts/core/types/Errors.sol"; +// Move to types struct EIP712Signature { address signer; uint8 v; @@ -81,12 +82,12 @@ abstract contract RestrictedSignersRule is MetadataBased { } function _configure(bytes32 configSalt, KeyValue[] calldata ruleParams) internal virtual { - require(ruleParams.length > 0); - require(ruleParams[0].key == PARAM__RESTRICTED_SIGNERS); + require(ruleParams.length > 0, Errors.InvalidParameter()); + require(ruleParams[0].key == PARAM__RESTRICTED_SIGNERS, Errors.InvalidParameter()); (address[] memory signers, string[] memory labels, bool[] memory isWhitelisted) = abi.decode(ruleParams[0].value, (address[], string[], bool[])); - require(signers.length == isWhitelisted.length); - require(signers.length == labels.length); + require(signers.length == isWhitelisted.length, Errors.InvalidParameter()); + require(signers.length == labels.length, Errors.InvalidParameter()); for (uint256 i = 0; i < signers.length; i++) { bool wasWhitelisted = $rulesStorage(msg.sender, configSalt).isWhitelistedSigner[signers[i]]; if (wasWhitelisted == isWhitelisted[i]) { @@ -115,15 +116,15 @@ abstract contract RestrictedSignersRule is MetadataBased { RestrictedSignerMessage memory message = RestrictedSignerMessage(functionSelector, abiEncodedFunctionParams, signature.nonce, signature.deadline); if (block.timestamp > signature.deadline) { - revert("Errors.SignatureExpired()"); + revert Errors.Expired(); } if ($rulesStorage(msg.sender, configSalt).wasSignerNonceUsed[signature.signer][signature.nonce]) { - revert("Errors.SignatureNonceUsed()"); + revert Errors.NonceUsed(); } $rulesStorage(msg.sender, configSalt).wasSignerNonceUsed[signature.signer][signature.nonce] = true; emit Lens_RestrictedSignersRule_SignerNonceUsed(signature.signer, signature.nonce); if (!$rulesStorage(msg.sender, configSalt).isWhitelistedSigner[signature.signer]) { - revert("Errors.SignerNotWhitelisted()"); + revert Errors.WrongSigner(); } bytes32 hashStruct = _calculateMessageHashStruct(message); bytes32 digest = _calculateDigest(hashStruct); @@ -160,18 +161,18 @@ abstract contract RestrictedSignersRule is MetadataBased { function _validateRecoveredAddress(bytes32 digest, EIP712Signature memory signature) private view { if (block.timestamp > signature.deadline) { - revert("Errors.SignatureExpired()"); + revert Errors.Expired(); } // If the expected address is a contract, check the signature there. if (signature.signer.code.length != 0) { bytes memory concatenatedSig = abi.encodePacked(signature.r, signature.s, signature.v); if (IERC1271(signature.signer).isValidSignature(digest, concatenatedSig) != EIP1271_MAGIC_VALUE) { - revert("Errors.SignatureInvalid()"); + revert Errors.InvalidSignature(); } } else { address recoveredAddress = ecrecover(digest, signature.v, signature.r, signature.s); if (recoveredAddress == address(0) || recoveredAddress != signature.signer) { - revert("Errors.SignatureInvalid()"); + revert Errors.WrongSigner(); } } } diff --git a/contracts/rules/base/SimplePaymentRule.sol b/contracts/rules/base/SimplePaymentRule.sol index 49854b97..2f133383 100644 --- a/contracts/rules/base/SimplePaymentRule.sol +++ b/contracts/rules/base/SimplePaymentRule.sol @@ -5,6 +5,7 @@ pragma solidity ^0.8.26; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {MetadataBased} from "contracts/core/base/MetadataBased.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; abstract contract SimplePaymentRule is MetadataBased { using SafeERC20 for IERC20; @@ -43,7 +44,7 @@ abstract contract SimplePaymentRule is MetadataBased { } function _validatePaymentConfiguration(PaymentConfiguration memory configuration) internal view virtual { - require(configuration.amount > 0, "Errors.CannotSetZeroAmount()"); + require(configuration.amount > 0, Errors.InvalidParameter()); // Expects token to support ERC-20 interface, we call balanceOf and expect it to not revert IERC20(configuration.token).balanceOf(address(this)); } @@ -53,11 +54,11 @@ abstract contract SimplePaymentRule is MetadataBased { PaymentConfiguration memory expectedConfiguration, address payer ) internal view virtual { - require(configuration.token == expectedConfiguration.token, "Errors.UnexpectedToken()"); - require(configuration.amount == expectedConfiguration.amount, "Errors.UnexpectedAmount()"); - require(configuration.recipient == expectedConfiguration.recipient, "Errors.UnexpectedRecipient()"); + require(configuration.token == expectedConfiguration.token, Errors.InvalidParameter()); + require(configuration.amount == expectedConfiguration.amount, Errors.InvalidParameter()); + require(configuration.recipient == expectedConfiguration.recipient, Errors.InvalidParameter()); // Requires payer to trust the msg.sender, which is acting as the primitive - require(_isTrusted[payer][msg.sender]); + require(_isTrusted[payer][msg.sender], Errors.Untrusted()); } function _processPayment( diff --git a/contracts/rules/base/TokenGatedRule.sol b/contracts/rules/base/TokenGatedRule.sol index 30e0801f..f8b1aab7 100644 --- a/contracts/rules/base/TokenGatedRule.sol +++ b/contracts/rules/base/TokenGatedRule.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.26; import {IERC1155} from "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; import {MetadataBased} from "contracts/core/base/MetadataBased.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; interface IToken { /** @@ -38,7 +39,7 @@ abstract contract TokenGatedRule is MetadataBased { } function _validateTokenGateConfiguration(TokenGateConfiguration memory configuration) internal view { - require(configuration.amount > 0, "Errors.CannotSetZeroAmount()"); + require(configuration.amount > 0, Errors.InvalidParameter()); if (configuration.tokenStandard == ERC20 || configuration.tokenStandard == ERC721) { // Expects token to support ERC-20/ERC-721 balanceOf by not reverting IToken(configuration.token).balanceOf(address(this)); @@ -46,12 +47,12 @@ abstract contract TokenGatedRule is MetadataBased { // Expects token to support ERC-1155 balanceOf by not reverting IERC1155(configuration.token).balanceOf(address(this), configuration.typeId); } else { - revert("Errors.InvalidTokenStandard()"); + revert Errors.InvalidParameter(); } } function _validateTokenBalance(TokenGateConfiguration memory configuration, address owner) internal view { - require(_checkTokenBalance(configuration, owner), "Errors.InsufficientTokenBalance()"); + require(_checkTokenBalance(configuration, owner), Errors.NotEnough()); } function _checkTokenBalance(TokenGateConfiguration memory configuration, address owner) diff --git a/contracts/rules/feed/GroupGatedFeedRule.sol b/contracts/rules/feed/GroupGatedFeedRule.sol index bb306856..133842f7 100644 --- a/contracts/rules/feed/GroupGatedFeedRule.sol +++ b/contracts/rules/feed/GroupGatedFeedRule.sol @@ -7,6 +7,7 @@ import {IFeedRule} from "contracts/core/interfaces/IFeedRule.sol"; import {IGroup} from "contracts/core/interfaces/IGroup.sol"; import {KeyValue, RuleChange} from "contracts/core/types/Types.sol"; import {MetadataBased} from "contracts/core/base/MetadataBased.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; /// @custom:keccak lens.param.group bytes32 constant PARAM__GROUP = 0xa92ea569d1a9f915f96759ba7cea5f135d011c442b0508dbef76a309e55f4458; @@ -42,7 +43,7 @@ contract GroupGatedFeedRule is IFeedRule, MetadataBased { KeyValue[] calldata, /* primitiveParams */ KeyValue[] calldata /* ruleParams */ ) external view override { - require(IGroup(_groupGate[msg.sender][configSalt]).isMember(postParams.author), "NotAMember()"); + require(IGroup(_groupGate[msg.sender][configSalt]).isMember(postParams.author), Errors.NotAMember()); } function processEditPost( @@ -52,7 +53,7 @@ contract GroupGatedFeedRule is IFeedRule, MetadataBased { KeyValue[] calldata, /* primitiveParams */ KeyValue[] calldata /* ruleParams */ ) external pure override { - revert(); + revert Errors.NotImplemented(); } function processRemovePost( @@ -61,7 +62,7 @@ contract GroupGatedFeedRule is IFeedRule, MetadataBased { KeyValue[] calldata, /* primitiveParams */ KeyValue[] calldata /* ruleParams */ ) external pure override { - revert(); + revert Errors.NotImplemented(); } function processPostRuleChanges( @@ -70,6 +71,6 @@ contract GroupGatedFeedRule is IFeedRule, MetadataBased { RuleChange[] calldata, /* ruleChanges */ KeyValue[] calldata /* ruleParams */ ) external pure override { - revert(); + revert Errors.NotImplemented(); } } diff --git a/contracts/rules/feed/SimplePaymentFeedRule.sol b/contracts/rules/feed/SimplePaymentFeedRule.sol index 252fb763..029b9d9a 100644 --- a/contracts/rules/feed/SimplePaymentFeedRule.sol +++ b/contracts/rules/feed/SimplePaymentFeedRule.sol @@ -9,6 +9,7 @@ import {AccessControlLib} from "contracts/core/libraries/AccessControlLib.sol"; import {IAccessControl} from "contracts/core/interfaces/IAccessControl.sol"; import {KeyValue, RuleChange} from "contracts/core/types/Types.sol"; import {Events} from "contracts/core/types/Events.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; contract SimplePaymentFeedRule is SimplePaymentRule, IFeedRule { using AccessControlLib for IAccessControl; @@ -60,7 +61,7 @@ contract SimplePaymentFeedRule is SimplePaymentRule, IFeedRule { KeyValue[] calldata, /* primitiveParams */ KeyValue[] calldata /* ruleParams */ ) external pure override { - revert(); + revert Errors.NotImplemented(); } function processRemovePost( @@ -69,7 +70,7 @@ contract SimplePaymentFeedRule is SimplePaymentRule, IFeedRule { KeyValue[] calldata, /* primitiveParams */ KeyValue[] calldata /* ruleParams */ ) external pure override { - revert(); + revert Errors.NotImplemented(); } function processPostRuleChanges( @@ -78,7 +79,7 @@ contract SimplePaymentFeedRule is SimplePaymentRule, IFeedRule { RuleChange[] calldata, /* ruleChanges */ KeyValue[] calldata /* ruleParams */ ) external pure override { - revert(); + revert Errors.NotImplemented(); } function _processPayment( diff --git a/contracts/rules/feed/TokenGatedFeedRule.sol b/contracts/rules/feed/TokenGatedFeedRule.sol index 042490b4..f88c2d97 100644 --- a/contracts/rules/feed/TokenGatedFeedRule.sol +++ b/contracts/rules/feed/TokenGatedFeedRule.sol @@ -9,6 +9,7 @@ import {IAccessControl} from "contracts/core/interfaces/IAccessControl.sol"; import {AccessControlLib} from "contracts/core/libraries/AccessControlLib.sol"; import {KeyValue, RuleChange} from "contracts/core/types/Types.sol"; import {Events} from "contracts/core/types/Events.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; contract TokenGatedFeedRule is TokenGatedRule, IFeedRule { using AccessControlLib for IAccessControl; @@ -59,7 +60,7 @@ contract TokenGatedFeedRule is TokenGatedRule, IFeedRule { KeyValue[] calldata, /* primitiveParams */ KeyValue[] calldata /* ruleParams */ ) external pure override { - revert(); + revert Errors.NotImplemented(); } function processRemovePost( @@ -68,7 +69,7 @@ contract TokenGatedFeedRule is TokenGatedRule, IFeedRule { KeyValue[] calldata, /* primitiveParams */ KeyValue[] calldata /* ruleParams */ ) external pure override { - revert(); + revert Errors.NotImplemented(); } function processPostRuleChanges( @@ -77,7 +78,7 @@ contract TokenGatedFeedRule is TokenGatedRule, IFeedRule { RuleChange[] calldata, /* ruleChanges */ KeyValue[] calldata /* ruleParams */ ) external pure override { - revert(); + revert Errors.NotImplemented(); } function _validateTokenBalance( diff --git a/contracts/rules/graph/GroupGatedGraphRule.sol b/contracts/rules/graph/GroupGatedGraphRule.sol index 4855215d..6f990860 100644 --- a/contracts/rules/graph/GroupGatedGraphRule.sol +++ b/contracts/rules/graph/GroupGatedGraphRule.sol @@ -9,6 +9,7 @@ import {KeyValue, RuleChange} from "contracts/core/types/Types.sol"; import {Events} from "contracts/core/types/Events.sol"; import {IGroup} from "contracts/core/interfaces/IGroup.sol"; import {MetadataBased} from "contracts/core/base/MetadataBased.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; contract GroupGatedGraphRule is IGraphRule, MetadataBased { using AccessControlLib for IAccessControl; @@ -79,7 +80,7 @@ contract GroupGatedGraphRule is IGraphRule, MetadataBased { KeyValue[] calldata, /* primitiveParams */ KeyValue[] calldata /* ruleParams */ ) external pure override { - revert(); + revert Errors.NotImplemented(); } function processFollowRuleChanges( @@ -88,12 +89,12 @@ contract GroupGatedGraphRule is IGraphRule, MetadataBased { RuleChange[] calldata, /* ruleChanges */ KeyValue[] calldata /* ruleParams */ ) external pure override { - revert(); + revert Errors.NotImplemented(); } function _validateGroupMembership(address accessControl, address group, address account) internal view { if (!accessControl.hasAccess(account, PID__SKIP_TOKEN_GATE)) { - require(IGroup(group).isMember(account), "NotAMember()"); + require(IGroup(group).isMember(account), Errors.NotAMember()); } } diff --git a/contracts/rules/graph/TokenGatedGraphRule.sol b/contracts/rules/graph/TokenGatedGraphRule.sol index 176343dc..b2e4ac5e 100644 --- a/contracts/rules/graph/TokenGatedGraphRule.sol +++ b/contracts/rules/graph/TokenGatedGraphRule.sol @@ -8,6 +8,7 @@ import {IAccessControl} from "contracts/core/interfaces/IAccessControl.sol"; import {AccessControlLib} from "contracts/core/libraries/AccessControlLib.sol"; import {KeyValue, RuleChange} from "contracts/core/types/Types.sol"; import {Events} from "contracts/core/types/Events.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; contract TokenGatedGraphRule is TokenGatedRule, IGraphRule { using AccessControlLib for IAccessControl; @@ -69,7 +70,7 @@ contract TokenGatedGraphRule is TokenGatedRule, IGraphRule { KeyValue[] calldata, /* primitiveParams */ KeyValue[] calldata /* ruleParams */ ) external pure { - revert(); + revert Errors.NotImplemented(); } function processFollowRuleChanges( @@ -78,7 +79,7 @@ contract TokenGatedGraphRule is TokenGatedRule, IGraphRule { RuleChange[] calldata, /* ruleChanges */ KeyValue[] calldata /* ruleParams */ ) external pure override { - revert(); + revert Errors.NotImplemented(); } function _validateTokenBalance( diff --git a/contracts/rules/group/BanMemberGroupRule.sol b/contracts/rules/group/BanMemberGroupRule.sol index f60a144e..aed065ab 100644 --- a/contracts/rules/group/BanMemberGroupRule.sol +++ b/contracts/rules/group/BanMemberGroupRule.sol @@ -8,6 +8,7 @@ import {AccessControlLib} from "contracts/core/libraries/AccessControlLib.sol"; import {Events} from "contracts/core/types/Events.sol"; import {KeyValue} from "contracts/core/types/Types.sol"; import {MetadataBased} from "contracts/core/base/MetadataBased.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; contract BanMemberGroupRule is IGroupRule, MetadataBased { using AccessControlLib for IAccessControl; @@ -80,7 +81,7 @@ contract BanMemberGroupRule is IGroupRule, MetadataBased { if (_isMemberBanned[msg.sender][configSalt][account]) { for (uint256 i = 0; i < ruleParams.length; i++) { if (ruleParams[i].key == PARAM__BAN_MEMBER) { - require(!abi.decode(ruleParams[i].value, (bool))); // Cannot ban while adding to the group. + require(!abi.decode(ruleParams[i].value, (bool)), Errors.InvalidParameter()); // Cannot ban while adding to the group. _isMemberBanned[msg.sender][configSalt][account] = false; _accessControl[msg.sender][configSalt].requireAccess(originalMsgSender, PID__UNBAN_MEMBER); emit Lens_BanMemberGroupRule_MemberUnbanned(msg.sender, configSalt, account, originalMsgSender); @@ -88,7 +89,7 @@ contract BanMemberGroupRule is IGroupRule, MetadataBased { } } // If member is banned and the param to unban was not passed, revert. - revert(); + revert Errors.Banned(); } } @@ -107,7 +108,7 @@ contract BanMemberGroupRule is IGroupRule, MetadataBased { emit Lens_BanMemberGroupRule_MemberBanned(msg.sender, configSalt, account, originalMsgSender); } else { // Cannot unban while kicking from the group. - require(!_isMemberBanned[msg.sender][configSalt][account]); + require(!_isMemberBanned[msg.sender][configSalt][account], Errors.InvalidParameter()); } return; } @@ -120,7 +121,7 @@ contract BanMemberGroupRule is IGroupRule, MetadataBased { KeyValue[] calldata, /* primitiveParams */ KeyValue[] calldata /* ruleParams */ ) external view override { - require(!_isMemberBanned[msg.sender][configSalt][account]); + require(!_isMemberBanned[msg.sender][configSalt][account], Errors.Banned()); } function processLeaving( @@ -129,6 +130,6 @@ contract BanMemberGroupRule is IGroupRule, MetadataBased { KeyValue[] calldata, /* primitiveParams */ KeyValue[] calldata /* ruleParams */ ) external pure override { - revert(); + revert Errors.NotImplemented(); } } diff --git a/contracts/rules/group/MembershipApprovalGroupRule.sol b/contracts/rules/group/MembershipApprovalGroupRule.sol index 835c01fb..efb4e4e5 100644 --- a/contracts/rules/group/MembershipApprovalGroupRule.sol +++ b/contracts/rules/group/MembershipApprovalGroupRule.sol @@ -8,6 +8,7 @@ import {AccessControlLib} from "contracts/core/libraries/AccessControlLib.sol"; import {Events} from "contracts/core/types/Events.sol"; import {KeyValue} from "contracts/core/types/Types.sol"; import {MetadataBased} from "contracts/core/base/MetadataBased.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; contract MembershipApprovalGroupRule is IGroupRule, MetadataBased { using AccessControlLib for IAccessControl; @@ -45,19 +46,19 @@ contract MembershipApprovalGroupRule is IGroupRule, MetadataBased { } function requestMembership(bytes32 configSalt, address group) external { - require(!_membershipRequests[group][msg.sender][configSalt].isRequested); + require(!_membershipRequests[group][msg.sender][configSalt].isRequested, Errors.AlreadyExists()); _membershipRequests[group][msg.sender][configSalt].isRequested = true; emit Lens_ApprovalGroupRule_MembershipRequested(group, msg.sender); } function cancelMembershipRequest(bytes32 configSalt, address group) external { - require(_membershipRequests[group][msg.sender][configSalt].isRequested); + require(_membershipRequests[group][msg.sender][configSalt].isRequested, Errors.DoesNotExist()); delete _membershipRequests[group][msg.sender][configSalt]; emit Lens_ApprovalGroupRule_MembershipRequestCancelled(group, msg.sender); } function answerMembershipRequest(bytes32 configSalt, address group, address account, bool isApproved) external { - require(_membershipRequests[group][account][configSalt].isRequested); + require(_membershipRequests[group][account][configSalt].isRequested, Errors.DoesNotExist()); if (isApproved) { _membershipRequests[group][account][configSalt].isApproved = isApproved; emit Lens_ApprovalGroupRule_MembershipApproved(group, account, msg.sender); @@ -65,7 +66,7 @@ contract MembershipApprovalGroupRule is IGroupRule, MetadataBased { delete _membershipRequests[group][account][configSalt]; emit Lens_ApprovalGroupRule_MembershipRejected(group, account, msg.sender); } - require(_accessControl[group][configSalt].hasAccess(msg.sender, PID__APPROVE_MEMBER)); + _accessControl[group][configSalt].requireAccess(msg.sender, PID__APPROVE_MEMBER); } function configure(bytes32 configSalt, KeyValue[] calldata ruleParams) external override { @@ -88,7 +89,7 @@ contract MembershipApprovalGroupRule is IGroupRule, MetadataBased { KeyValue[] calldata /* ruleParams */ ) external override { if (!_membershipRequests[msg.sender][account][configSalt].isApproved) { - require(_accessControl[msg.sender][configSalt].hasAccess(originalMsgSender, PID__APPROVE_MEMBER)); + _accessControl[msg.sender][configSalt].requireAccess(originalMsgSender, PID__APPROVE_MEMBER); emit Lens_ApprovalGroupRule_MembershipApproved(msg.sender, account, originalMsgSender); } delete _membershipRequests[msg.sender][account][configSalt]; @@ -101,7 +102,7 @@ contract MembershipApprovalGroupRule is IGroupRule, MetadataBased { KeyValue[] calldata, /* primitiveParams */ KeyValue[] calldata /* ruleParams */ ) external override { - require(_membershipRequests[msg.sender][account][configSalt].isApproved); + require(_membershipRequests[msg.sender][account][configSalt].isApproved, Errors.NotAllowed()); delete _membershipRequests[msg.sender][account][configSalt]; emit Lens_ApprovalGroupRule_MembershipGranted(msg.sender, account); } @@ -113,7 +114,7 @@ contract MembershipApprovalGroupRule is IGroupRule, MetadataBased { KeyValue[] calldata, /* primitiveParams */ KeyValue[] calldata /* ruleParams */ ) external pure override { - revert(); + revert Errors.NotImplemented(); } function processLeaving( @@ -122,6 +123,6 @@ contract MembershipApprovalGroupRule is IGroupRule, MetadataBased { KeyValue[] calldata, /* primitiveParams */ KeyValue[] calldata /* ruleParams */ ) external pure override { - revert(); + revert Errors.NotImplemented(); } } diff --git a/contracts/rules/group/SimplePaymentGroupRule.sol b/contracts/rules/group/SimplePaymentGroupRule.sol index 5f75f7f1..8548ebd5 100644 --- a/contracts/rules/group/SimplePaymentGroupRule.sol +++ b/contracts/rules/group/SimplePaymentGroupRule.sol @@ -8,6 +8,7 @@ import {AccessControlLib} from "contracts/core/libraries/AccessControlLib.sol"; import {IAccessControl} from "contracts/core/interfaces/IAccessControl.sol"; import {KeyValue} from "contracts/core/types/Types.sol"; import {Events} from "contracts/core/types/Events.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; contract SimplePaymentGroupRule is SimplePaymentRule, IGroupRule { using AccessControlLib for IAccessControl; @@ -44,7 +45,7 @@ contract SimplePaymentGroupRule is SimplePaymentRule, IGroupRule { KeyValue[] calldata, /* primitiveParams */ KeyValue[] calldata /* ruleParams */ ) external pure { - revert(); + revert Errors.NotImplemented(); } function processRemoval( @@ -54,7 +55,7 @@ contract SimplePaymentGroupRule is SimplePaymentRule, IGroupRule { KeyValue[] calldata, /* primitiveParams */ KeyValue[] calldata /* ruleParams */ ) external pure { - revert(); + revert Errors.NotImplemented(); } function processJoining( @@ -77,7 +78,7 @@ contract SimplePaymentGroupRule is SimplePaymentRule, IGroupRule { KeyValue[] calldata, /* primitiveParams */ KeyValue[] calldata /* ruleParams */ ) external pure { - revert(); + revert Errors.NotImplemented(); } function _processPayment( diff --git a/contracts/rules/group/TokenGatedGroupRule.sol b/contracts/rules/group/TokenGatedGroupRule.sol index 667c9b88..3a63e4eb 100644 --- a/contracts/rules/group/TokenGatedGroupRule.sol +++ b/contracts/rules/group/TokenGatedGroupRule.sol @@ -8,6 +8,7 @@ import {IAccessControl} from "contracts/core/interfaces/IAccessControl.sol"; import {AccessControlLib} from "contracts/core/libraries/AccessControlLib.sol"; import {KeyValue} from "contracts/core/types/Types.sol"; import {Events} from "contracts/core/types/Events.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; contract TokenGatedGroupRule is TokenGatedRule, IGroupRule { using AccessControlLib for IAccessControl; @@ -44,7 +45,7 @@ contract TokenGatedGroupRule is TokenGatedRule, IGroupRule { KeyValue[] calldata, /* primitiveParams */ KeyValue[] calldata /* ruleParams */ ) external pure { - revert(); + revert Errors.NotImplemented(); } function processRemoval( @@ -55,7 +56,7 @@ contract TokenGatedGroupRule is TokenGatedRule, IGroupRule { KeyValue[] calldata /* ruleParams */ ) external view { // Anyone can kick out member of the group if they no longer hold the required token balance: - require(!_checkTokenBalance(_configuration[msg.sender][configSalt].tokenGate, account)); + require(!_checkTokenBalance(_configuration[msg.sender][configSalt].tokenGate, account), Errors.NotAllowed()); } function processJoining( @@ -77,7 +78,7 @@ contract TokenGatedGroupRule is TokenGatedRule, IGroupRule { KeyValue[] calldata, /* primitiveParams */ KeyValue[] calldata /* ruleParams */ ) external pure { - revert(); + revert Errors.NotImplemented(); } function _validateTokenBalance( diff --git a/contracts/rules/namespace/UsernameCharsetNamespaceRule.sol b/contracts/rules/namespace/UsernameCharsetNamespaceRule.sol index a58b8826..ac4a0e1c 100644 --- a/contracts/rules/namespace/UsernameCharsetNamespaceRule.sol +++ b/contracts/rules/namespace/UsernameCharsetNamespaceRule.sol @@ -8,6 +8,7 @@ import {AccessControlLib} from "contracts/core/libraries/AccessControlLib.sol"; import {Events} from "contracts/core/types/Events.sol"; import {KeyValue} from "contracts/core/types/Types.sol"; import {MetadataBased} from "contracts/core/base/MetadataBased.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; contract UsernameCharsetNamespaceRule is INamespaceRule, MetadataBased { event Lens_Rule_MetadataURISet(string metadataURI); @@ -91,7 +92,7 @@ contract UsernameCharsetNamespaceRule is INamespaceRule, MetadataBased { KeyValue[] calldata, /* primitiveParams */ KeyValue[] calldata /* ruleParams */ ) external pure override { - revert(); + revert Errors.NotImplemented(); } function processAssigning( @@ -102,7 +103,7 @@ contract UsernameCharsetNamespaceRule is INamespaceRule, MetadataBased { KeyValue[] calldata, /* primitiveParams */ KeyValue[] calldata /* ruleParams */ ) external pure override { - revert(); + revert Errors.NotImplemented(); } function processUnassigning( @@ -113,7 +114,7 @@ contract UsernameCharsetNamespaceRule is INamespaceRule, MetadataBased { KeyValue[] calldata, /* primitiveParams */ KeyValue[] calldata /* ruleParams */ ) external pure override { - revert(); + revert Errors.NotImplemented(); } function _processRestrictions(string calldata username, CharsetRestrictions memory charsetRestrictions) @@ -121,39 +122,24 @@ contract UsernameCharsetNamespaceRule is INamespaceRule, MetadataBased { pure { // Cannot start with a character in the cannotStartWith charset - require( - !_isInCharset(bytes(username)[0], charsetRestrictions.cannotStartWith), - "UsernameCharsetRule: Username cannot start with specified character" - ); + require(!_isInCharset(bytes(username)[0], charsetRestrictions.cannotStartWith), Errors.CannotStartWithThat()); // Check if the username contains only allowed characters for (uint256 i = 0; i < bytes(username).length; i++) { bytes1 char = bytes(username)[i]; // Check disallowed chars first - require( - !_isInCharset(char, charsetRestrictions.customDisallowedCharset), - "UsernameCharsetRule: Username contains disallowed character" - ); + require(!_isInCharset(char, charsetRestrictions.customDisallowedCharset), Errors.NotAllowed()); // Check allowed charsets next if (_isNumeric(char)) { - require(charsetRestrictions.allowNumeric, "UsernameCharsetRule: Username cannot contain numbers"); + require(charsetRestrictions.allowNumeric, Errors.NotAllowed()); } else if (_isLatinLowercase(char)) { - require( - charsetRestrictions.allowLatinLowercase, - "UsernameCharsetRule: Username cannot contain lowercase latin characters" - ); + require(charsetRestrictions.allowLatinLowercase, Errors.NotAllowed()); } else if (_isLatinUppercase(char)) { - require( - charsetRestrictions.allowLatinUppercase, - "UsernameCharsetRule: Username cannot contain uppercase latin characters" - ); + require(charsetRestrictions.allowLatinUppercase, Errors.NotAllowed()); } else if (bytes(charsetRestrictions.customAllowedCharset).length > 0) { - require( - _isInCharset(char, charsetRestrictions.customAllowedCharset), - "UsernameCharsetRule: Username contains disallowed character" - ); + require(_isInCharset(char, charsetRestrictions.customAllowedCharset), Errors.NotAllowed()); } else { // If not in any of the above charsets, reject - revert("UsernameCharsetRule: Username contains disallowed character"); + revert Errors.NotAllowed(); } } } diff --git a/contracts/rules/namespace/UsernameLengthNamespaceRule.sol b/contracts/rules/namespace/UsernameLengthNamespaceRule.sol index 0e5b8e93..bee137ba 100644 --- a/contracts/rules/namespace/UsernameLengthNamespaceRule.sol +++ b/contracts/rules/namespace/UsernameLengthNamespaceRule.sol @@ -8,6 +8,7 @@ import {AccessControlLib} from "contracts/core/libraries/AccessControlLib.sol"; import {Events} from "contracts/core/types/Events.sol"; import {KeyValue} from "contracts/core/types/Types.sol"; import {MetadataBased} from "contracts/core/base/MetadataBased.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; contract UsernameLengthNamespaceRule is INamespaceRule, MetadataBased { event Lens_Rule_MetadataURISet(string metadataURI); @@ -60,7 +61,8 @@ contract UsernameLengthNamespaceRule is INamespaceRule, MetadataBased { configuration.accessControl.verifyHasAccessFunction(); require( configuration.lengthRestrictions.max == 0 - || configuration.lengthRestrictions.min <= configuration.lengthRestrictions.max + || configuration.lengthRestrictions.min <= configuration.lengthRestrictions.max, + Errors.InvalidParameter() ); // Min length cannot be greater than max length _configuration[msg.sender][configSalt] = configuration; } @@ -79,13 +81,13 @@ contract UsernameLengthNamespaceRule is INamespaceRule, MetadataBased { configuration.lengthRestrictions.min != 0 && !configuration.accessControl.hasAccess(originalMsgSender, PID__SKIP_MIN_LENGTH_RESTRICTION) ) { - require(usernameLength >= configuration.lengthRestrictions.min, "Username: too short"); + require(usernameLength >= configuration.lengthRestrictions.min, Errors.InvalidParameter()); } if ( configuration.lengthRestrictions.max != 0 && !configuration.accessControl.hasAccess(originalMsgSender, PID__SKIP_MAX_LENGTH_RESTRICTION) ) { - require(usernameLength <= configuration.lengthRestrictions.max, "Username: too long"); + require(usernameLength <= configuration.lengthRestrictions.max, Errors.InvalidParameter()); } } @@ -96,7 +98,7 @@ contract UsernameLengthNamespaceRule is INamespaceRule, MetadataBased { KeyValue[] calldata, /* primitiveParams */ KeyValue[] calldata /* ruleParams */ ) external pure override { - revert(); + revert Errors.NotImplemented(); } function processAssigning( @@ -107,7 +109,7 @@ contract UsernameLengthNamespaceRule is INamespaceRule, MetadataBased { KeyValue[] calldata, /* primitiveParams */ KeyValue[] calldata /* ruleParams */ ) external pure override { - revert(); + revert Errors.NotImplemented(); } function processUnassigning( @@ -118,7 +120,7 @@ contract UsernameLengthNamespaceRule is INamespaceRule, MetadataBased { KeyValue[] calldata, /* primitiveParams */ KeyValue[] calldata /* ruleParams */ ) external pure override { - revert(); + revert Errors.NotImplemented(); } function _extractConfigurationFromParams(KeyValue[] calldata params) internal pure returns (Configuration memory) { diff --git a/contracts/rules/namespace/UsernameReservedNamespaceRule.sol b/contracts/rules/namespace/UsernameReservedNamespaceRule.sol index 9ce13e03..0621b0c9 100644 --- a/contracts/rules/namespace/UsernameReservedNamespaceRule.sol +++ b/contracts/rules/namespace/UsernameReservedNamespaceRule.sol @@ -8,6 +8,7 @@ import {AccessControlLib} from "contracts/core/libraries/AccessControlLib.sol"; import {Events} from "contracts/core/types/Events.sol"; import {KeyValue} from "contracts/core/types/Types.sol"; import {MetadataBased} from "contracts/core/base/MetadataBased.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; contract UsernameReservedNamespaceRule is INamespaceRule, MetadataBased { event Lens_Rule_MetadataURISet(string metadataURI); @@ -61,7 +62,10 @@ contract UsernameReservedNamespaceRule is INamespaceRule, MetadataBased { } else if (ruleParams[i].key == PARAM__USERNAMES_TO_RESERVE) { string[] memory usernamesToReserve = abi.decode(ruleParams[i].value, (string[])); for (uint256 j = 0; j < usernamesToReserve.length; j++) { - require(!_isUsernameReserved[msg.sender][configSalt][usernamesToReserve[j]]); + require( + !_isUsernameReserved[msg.sender][configSalt][usernamesToReserve[j]], + Errors.RedundantStateChange() + ); _isUsernameReserved[msg.sender][configSalt][usernamesToReserve[j]] = true; emit Lens_UsernameReservedNamespaceRule_UsernameReserved( msg.sender, configSalt, usernamesToReserve[j], usernamesToReserve[j] @@ -70,7 +74,9 @@ contract UsernameReservedNamespaceRule is INamespaceRule, MetadataBased { } else if (ruleParams[i].key == PARAM__USERNAMES_TO_RELEASE) { string[] memory usernamesToRelease = abi.decode(ruleParams[i].value, (string[])); for (uint256 j = 0; j < usernamesToRelease.length; j++) { - require(_isUsernameReserved[msg.sender][configSalt][usernamesToRelease[j]]); + require( + _isUsernameReserved[msg.sender][configSalt][usernamesToRelease[j]], Errors.RedundantStateChange() + ); _isUsernameReserved[msg.sender][configSalt][usernamesToRelease[j]] = false; emit Lens_UsernameReservedNamespaceRule_UsernameReleased( msg.sender, configSalt, usernamesToRelease[j], usernamesToRelease[j] @@ -105,7 +111,7 @@ contract UsernameReservedNamespaceRule is INamespaceRule, MetadataBased { KeyValue[] calldata, /* primitiveParams */ KeyValue[] calldata /* ruleParams */ ) external pure override { - revert(); + revert Errors.NotImplemented(); } function processAssigning( @@ -116,7 +122,7 @@ contract UsernameReservedNamespaceRule is INamespaceRule, MetadataBased { KeyValue[] calldata, /* primitiveParams */ KeyValue[] calldata /* ruleParams */ ) external pure override { - revert(); + revert Errors.NotImplemented(); } function processUnassigning( @@ -127,6 +133,6 @@ contract UsernameReservedNamespaceRule is INamespaceRule, MetadataBased { KeyValue[] calldata, /* primitiveParams */ KeyValue[] calldata /* ruleParams */ ) external pure override { - revert(); + revert Errors.NotImplemented(); } } diff --git a/contracts/rules/post/FollowersOnlyPostRule.sol b/contracts/rules/post/FollowersOnlyPostRule.sol index ed2b4c20..8d9baa40 100644 --- a/contracts/rules/post/FollowersOnlyPostRule.sol +++ b/contracts/rules/post/FollowersOnlyPostRule.sol @@ -8,6 +8,7 @@ import {IFeed} from "contracts/core/interfaces/IFeed.sol"; import {KeyValue} from "contracts/core/types/Types.sol"; import {CreatePostParams, EditPostParams} from "contracts/core/interfaces/IFeed.sol"; import {MetadataBased} from "contracts/core/base/MetadataBased.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; contract FollowersOnlyPostRule is IPostRule, MetadataBased { event Lens_Rule_MetadataURISet(string metadataURI); @@ -52,7 +53,10 @@ contract FollowersOnlyPostRule is IPostRule, MetadataBased { } } IGraph(configuration.graph).isFollowing(address(this), msg.sender); // Verifies the provided address is a graph - require(configuration.repliesRestricted || configuration.repostsRestricted || configuration.quotesRestricted); + require( + configuration.repliesRestricted || configuration.repostsRestricted || configuration.quotesRestricted, + Errors.InvalidParameter() + ); _configuration[msg.sender][configSalt][postId] = configuration; } @@ -70,7 +74,9 @@ contract FollowersOnlyPostRule is IPostRule, MetadataBased { IGraph graph = IGraph(configuration.graph); address rootPostAuthor = feed.getPostAuthor(rootPostId); address newPostAuthor = feed.getPostAuthor(postId); - require(graph.isFollowing({followerAccount: newPostAuthor, targetAccount: rootPostAuthor})); + require( + graph.isFollowing({followerAccount: newPostAuthor, targetAccount: rootPostAuthor}), Errors.NotFollowing() + ); } } @@ -82,7 +88,7 @@ contract FollowersOnlyPostRule is IPostRule, MetadataBased { KeyValue[] calldata, /* primitiveParams */ KeyValue[] calldata /* ruleParams */ ) external pure override { - revert(); + revert Errors.NotImplemented(); } // TODO: This function smells weird, we should reconsider going back to the processQuote/Reply/Repost selectors... diff --git a/test/Account.t.sol b/test/Account.t.sol index 3b29a926..fcec540c 100644 --- a/test/Account.t.sol +++ b/test/Account.t.sol @@ -8,9 +8,8 @@ import {IAccount, AccountManagerPermissions} from "@extensions/account/IAccount. import {Account} from "@extensions/account/Account.sol"; import {Feed} from "@core/primitives/Feed/Feed.sol"; import {IFeed, Post, CreatePostParams} from "@core/interfaces/IFeed.sol"; -import {OwnerAdminOnlyAccessControl} from "@extensions/access/OwnerAdminOnlyAccessControl.sol"; -import {IAccessControl} from "@core/interfaces/IAccessControl.sol"; import {BaseDeployments} from "test/helpers/BaseDeployments.sol"; +import {Errors} from "@core/types/Errors.sol"; contract AccountTest is Test, BaseDeployments { address owner = makeAddr("OWNER"); @@ -135,19 +134,19 @@ contract AccountTest is Test, BaseDeployments { function testCannotAddAccountManager_Twice() public { vm.prank(owner); - vm.expectRevert("Account manager already exists"); + vm.expectRevert(Errors.RedundantStateChange.selector); account.addAccountManager(manager, AccountManagerPermissions(true, true, true, true)); } function testCannotAdd_Owner_AsAccountManager() public { vm.prank(owner); - vm.expectRevert("Cannot add owner as account manager"); + vm.expectRevert(Errors.InvalidParameter.selector); account.addAccountManager(owner, AccountManagerPermissions(true, true, true, true)); } function testCannotAdd_ZeroAddress_AsManagerTwiceOrWrongly() public { vm.prank(owner); - vm.expectRevert("Cannot add zero address as account manager"); + vm.expectRevert(Errors.InvalidParameter.selector); account.addAccountManager(address(0), AccountManagerPermissions(true, true, true, true)); } From f4f8751268346809dd43a1aefb5ba0a71a550b23 Mon Sep 17 00:00:00 2001 From: vicnaum Date: Wed, 8 Jan 2025 21:40:31 +0100 Subject: [PATCH 05/41] misc: add fuzzing, via_ir and zkSync compilation to foundry.toml --- foundry.toml | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/foundry.toml b/foundry.toml index 1abb8d9a..56a7e71a 100644 --- a/foundry.toml +++ b/foundry.toml @@ -6,11 +6,15 @@ test = 'test' cache_path = 'cache_forge' solc_version = '0.8.28' -# [profile.default.zksync] -# # Compile contracts for zkVM -# compile = true -# # Enable zkVM at startup, needs `compile = true` to have effect -# startup = true +[profile.default.fuzz] +runs = 1024 +no_zksync_reserved_addresses = true + +[profile.default.zksync] +# Compile contracts for zkVM +compile = true +# Enable zkVM at startup, needs `compile = true` to have effect +startup = true # # By default the latest version is used # zksolc = "1.5.0" # # By default the corresponding solc patched version from matter-labs is used @@ -24,9 +28,9 @@ solc_version = '0.8.28' # # Force compilation via EVMLA instead of Yul codegen pipeline # force_evmla = false # # Enable optimizer on zksolc (defaults to true) -# optimizer = true -# # zksolc optimizer mode (0 | 1 | 2 | 3 | s | z) -# optimizer_mode = '3' +optimizer = true +# zksolc optimizer mode (0 | 1 | 2 | 3 | s | z) +optimizer_mode = '1' # # zksolc optimizer details # optimizer_details = { ... } From f435b95ca13bfb5e647d769be9a162b970f36f28 Mon Sep 17 00:00:00 2001 From: vicnaum Date: Thu, 9 Jan 2025 15:17:47 +0100 Subject: [PATCH 06/41] misc: commented out all lines that caused stack-too-deep --- contracts/core/base/RuleBasedPrimitive.sol | 18 +- contracts/core/primitives/feed/Feed.sol | 64 ++--- .../core/primitives/feed/RuleBasedFeed.sol | 40 +-- .../core/primitives/graph/RuleBasedGraph.sol | 88 +++---- .../core/primitives/group/RuleBasedGroup.sol | 20 +- .../core/primitives/namespace/Namespace.sol | 28 +- .../namespace/RuleBasedNamespace.sol | 44 ++-- .../extensions/factories/LensFactory.sol | 242 +++++++++--------- contracts/migration/MigrationFeed.sol | 40 +-- foundry.toml | 7 +- test/factories/LensFactory.t.sol | 56 ++-- test/primitives/Namespace.t.sol | 24 +- 12 files changed, 337 insertions(+), 334 deletions(-) diff --git a/contracts/core/base/RuleBasedPrimitive.sol b/contracts/core/base/RuleBasedPrimitive.sol index 0a7478ec..7f92b03c 100644 --- a/contracts/core/base/RuleBasedPrimitive.sol +++ b/contracts/core/base/RuleBasedPrimitive.sol @@ -170,15 +170,15 @@ abstract contract RuleBasedPrimitive { ruleChange.selectorChanges[j].ruleSelector, entityId == 0 ? _supportedPrimitiveRuleSelectors() : _supportedEntityRuleSelectors() ); - rulesStorage._changeRulesSelectors( - ruleChanges[i].ruleAddress, - ruleChange.configSalt, - entityId, - ruleChanges[i].selectorChanges[j].ruleSelector, - ruleChanges[i].selectorChanges[j].isRequired, - ruleChanges[i].selectorChanges[j].enabled, - fn_emitSelectorEvent - ); + // rulesStorage._changeRulesSelectors( + // ruleChanges[i].ruleAddress, + // ruleChange.configSalt, + // entityId, + // ruleChanges[i].selectorChanges[j].ruleSelector, + // ruleChanges[i].selectorChanges[j].isRequired, + // ruleChanges[i].selectorChanges[j].enabled, + // fn_emitSelectorEvent + // ); } } if (entityId == 0) { diff --git a/contracts/core/primitives/feed/Feed.sol b/contracts/core/primitives/feed/Feed.sol index 357ac54a..b067c001 100644 --- a/contracts/core/primitives/feed/Feed.sol +++ b/contracts/core/primitives/feed/Feed.sol @@ -98,36 +98,36 @@ contract Feed is // Process rules of the Quote (if quoting) if (postParams.quotedPostId != 0) { // TODO: Maybe quotes shouldn't be limited by rules... Just a brave thought. Like quotations in real life. - uint256 rootOfQuotedPost = Core.$storage().posts[postParams.quotedPostId].rootPostId; - if (rootOfQuotedPost != rootPostId) { - _processPostCreationOnRootPost(rootOfQuotedPost, postId, postParams, customParams, quotedPostRulesParams); - } + // uint256 rootOfQuotedPost = Core.$storage().posts[postParams.quotedPostId].rootPostId; + // if (rootOfQuotedPost != rootPostId) { + // _processPostCreationOnRootPost(rootOfQuotedPost, postId, postParams, customParams, quotedPostRulesParams); + // } } if (postId != rootPostId) { require(postParams.ruleChanges.length == 0, Errors.CannotHaveRules()); // This covers the Reply or Repost cases - _processPostCreationOnRootPost(rootPostId, postId, postParams, customParams, rootPostRulesParams); + // _processPostCreationOnRootPost(rootPostId, postId, postParams, customParams, rootPostRulesParams); } else { _addPostRulesAtCreation(postId, postParams, feedRulesParams); } - emit Lens_Feed_PostCreated( - postId, - postParams.author, - authorPostSequentialId, - rootPostId, - postParams, - customParams, - feedRulesParams, - rootPostRulesParams, - quotedPostRulesParams, - source - ); - for (uint256 i = 0; i < postParams.extraData.length; i++) { - _setEntityExtraData(postId, postParams.extraData[i]); - emit Lens_Feed_Post_ExtraDataAdded( - postId, postParams.extraData[i].key, postParams.extraData[i].value, postParams.extraData[i].value - ); - } + // emit Lens_Feed_PostCreated( + // postId, + // postParams.author, + // authorPostSequentialId, + // rootPostId, + // postParams, + // customParams, + // feedRulesParams, + // rootPostRulesParams, + // quotedPostRulesParams, + // source + // ); + // for (uint256 i = 0; i < postParams.extraData.length; i++) { + // _setEntityExtraData(postId, postParams.extraData[i]); + // emit Lens_Feed_Post_ExtraDataAdded( + // postId, postParams.extraData[i].key, postParams.extraData[i].value, postParams.extraData[i].value + // ); + // } return postId; } @@ -165,18 +165,18 @@ contract Feed is storeSource: true, lastUpdatedSourceType: true }); - emit Lens_Feed_PostEdited( - postId, author, postParams, customParams, feedRulesParams, rootPostRulesParams, quotedPostRulesParams, source - ); + // emit Lens_Feed_PostEdited( + // postId, author, postParams, customParams, feedRulesParams, rootPostRulesParams, quotedPostRulesParams, source + // ); for (uint256 i = 0; i < postParams.extraData.length; i++) { if (wereExtraDataValuesSet[i]) { - emit Lens_Feed_Post_ExtraDataUpdated( - postId, postParams.extraData[i].key, postParams.extraData[i].value, postParams.extraData[i].value - ); + // emit Lens_Feed_Post_ExtraDataUpdated( + // postId, postParams.extraData[i].key, postParams.extraData[i].value, postParams.extraData[i].value + // ); } else { - emit Lens_Feed_Post_ExtraDataAdded( - postId, postParams.extraData[i].key, postParams.extraData[i].value, postParams.extraData[i].value - ); + // emit Lens_Feed_Post_ExtraDataAdded( + // postId, postParams.extraData[i].key, postParams.extraData[i].value, postParams.extraData[i].value + // ); } } } diff --git a/contracts/core/primitives/feed/RuleBasedFeed.sol b/contracts/core/primitives/feed/RuleBasedFeed.sol index d6967577..8d2ab2da 100644 --- a/contracts/core/primitives/feed/RuleBasedFeed.sol +++ b/contracts/core/primitives/feed/RuleBasedFeed.sol @@ -190,10 +190,10 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { ) { ruleCustomParams = rulesProcessingParams[j].ruleParams; } - (bool callNotReverted,) = encodeAndCall( - rule.ruleAddress, rule.configSalt, rootPostId, postId, postParams, customParams, ruleCustomParams - ); - require(callNotReverted, Errors.RequiredRuleReverted()); + // (bool callNotReverted,) = encodeAndCall( + // rule.ruleAddress, rule.configSalt, rootPostId, postId, postParams, customParams, ruleCustomParams + // ); + // require(callNotReverted, Errors.RequiredRuleReverted()); } } // Check any-of rules (OR-combined rules) @@ -207,12 +207,12 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { ) { ruleCustomParams = rulesProcessingParams[j].ruleParams; } - (bool callNotReverted,) = encodeAndCall( - rule.ruleAddress, rule.configSalt, rootPostId, postId, postParams, customParams, ruleCustomParams - ); - if (callNotReverted) { - return; // If any of the OR-combined rules passed, it means they succeed and we can return - } + // (bool callNotReverted,) = encodeAndCall( + // rule.ruleAddress, rule.configSalt, rootPostId, postId, postParams, customParams, ruleCustomParams + // ); + // if (callNotReverted) { + // return; // If any of the OR-combined rules passed, it means they succeed and we can return + // } } } // If there are any-of rules and it reached this point, it means all of them failed. @@ -344,10 +344,10 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { ) { ruleCustomParams = rulesProcessingParams[j].ruleParams; } - (bool callNotReverted,) = encodeAndCall( - rule.ruleAddress, rule.configSalt, rootPostId, postId, postParams, customParams, ruleCustomParams - ); - require(callNotReverted, Errors.RequiredRuleReverted()); + // (bool callNotReverted,) = encodeAndCall( + // rule.ruleAddress, rule.configSalt, rootPostId, postId, postParams, customParams, ruleCustomParams + // ); + // require(callNotReverted, Errors.RequiredRuleReverted()); } } // Check any-of rules (OR-combined rules) @@ -361,12 +361,12 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { ) { ruleCustomParams = rulesProcessingParams[j].ruleParams; } - (bool callNotReverted,) = encodeAndCall( - rule.ruleAddress, rule.configSalt, rootPostId, postId, postParams, customParams, ruleCustomParams - ); - if (callNotReverted) { - return; // If any of the OR-combined rules passed, it means they succeed and we can return - } + // (bool callNotReverted,) = encodeAndCall( + // rule.ruleAddress, rule.configSalt, rootPostId, postId, postParams, customParams, ruleCustomParams + // ); + // if (callNotReverted) { + // return; // If any of the OR-combined rules passed, it means they succeed and we can return + // } } } // If there are any-of rules and it reached this point, it means all of them failed. diff --git a/contracts/core/primitives/graph/RuleBasedGraph.sol b/contracts/core/primitives/graph/RuleBasedGraph.sol index 36a94ba3..7158d81f 100644 --- a/contracts/core/primitives/graph/RuleBasedGraph.sol +++ b/contracts/core/primitives/graph/RuleBasedGraph.sol @@ -331,16 +331,16 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive { ) { ruleCustomParams = rulesProcessingParams[j].ruleParams; } - (bool callNotReverted,) = encodeAndCall( - rule.ruleAddress, - rule.configSalt, - originalMsgSender, - followerAccount, - accountToUnfollow, - primitiveCustomParams, - ruleCustomParams - ); - require(callNotReverted, Errors.RequiredRuleReverted()); + // (bool callNotReverted,) = encodeAndCall( + // rule.ruleAddress, + // rule.configSalt, + // originalMsgSender, + // followerAccount, + // accountToUnfollow, + // primitiveCustomParams, + // ruleCustomParams + // ); + // require(callNotReverted, Errors.RequiredRuleReverted()); } } for (uint256 i = 0; i < rulesStorage.anyOfRules[ruleSelector].length; i++) { @@ -353,18 +353,18 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive { ) { ruleCustomParams = rulesProcessingParams[j].ruleParams; } - (bool callNotReverted,) = encodeAndCall( - rule.ruleAddress, - rule.configSalt, - originalMsgSender, - followerAccount, - accountToUnfollow, - primitiveCustomParams, - ruleCustomParams - ); - if (callNotReverted) { - return; // If any of the OR-combined rules passed, it means they succeed and we can return - } + // (bool callNotReverted,) = encodeAndCall( + // rule.ruleAddress, + // rule.configSalt, + // originalMsgSender, + // followerAccount, + // accountToUnfollow, + // primitiveCustomParams, + // ruleCustomParams + // ); + // if (callNotReverted) { + // return; // If any of the OR-combined rules passed, it means they succeed and we can return + // } } } // If there are any-of rules and it reached this point, it means all of them failed. @@ -394,16 +394,16 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive { ) { ruleCustomParams = rulesProcessingParams[j].ruleParams; } - (bool callNotReverted,) = encodeAndCall( - rule.ruleAddress, - rule.configSalt, - originalMsgSender, - followerAccount, - accountToFollow, - primitiveCustomParams, - ruleCustomParams - ); - require(callNotReverted, Errors.RequiredRuleReverted()); + // (bool callNotReverted,) = encodeAndCall( + // rule.ruleAddress, + // rule.configSalt, + // originalMsgSender, + // followerAccount, + // accountToFollow, + // primitiveCustomParams, + // ruleCustomParams + // ); + // require(callNotReverted, Errors.RequiredRuleReverted()); } } for (uint256 i = 0; i < rulesStorage.anyOfRules[ruleSelector].length; i++) { @@ -416,18 +416,18 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive { ) { ruleCustomParams = rulesProcessingParams[j].ruleParams; } - (bool callNotReverted,) = encodeAndCall( - rule.ruleAddress, - rule.configSalt, - originalMsgSender, - followerAccount, - accountToFollow, - primitiveCustomParams, - ruleCustomParams - ); - if (callNotReverted) { - return; // If any of the OR-combined rules passed, it means they succeed and we can return - } + // (bool callNotReverted,) = encodeAndCall( + // rule.ruleAddress, + // rule.configSalt, + // originalMsgSender, + // followerAccount, + // accountToFollow, + // primitiveCustomParams, + // ruleCustomParams + // ); + // if (callNotReverted) { + // return; // If any of the OR-combined rules passed, it means they succeed and we can return + // } } } // If there are any-of rules and it reached this point, it means all of them failed. diff --git a/contracts/core/primitives/group/RuleBasedGroup.sol b/contracts/core/primitives/group/RuleBasedGroup.sol index 05e25622..480aee7d 100644 --- a/contracts/core/primitives/group/RuleBasedGroup.sol +++ b/contracts/core/primitives/group/RuleBasedGroup.sol @@ -241,10 +241,10 @@ abstract contract RuleBasedGroup is IGroup, RuleBasedPrimitive { ) { ruleParams = rulesProcessingParams[j].ruleParams; } - (bool callNotReverted,) = encodeAndCall( - rule.ruleAddress, rule.configSalt, originalMsgSender, account, primitiveCustomParams, ruleParams - ); - require(callNotReverted, Errors.RequiredRuleReverted()); + // (bool callNotReverted,) = encodeAndCall( + // rule.ruleAddress, rule.configSalt, originalMsgSender, account, primitiveCustomParams, ruleParams + // ); + // require(callNotReverted, Errors.RequiredRuleReverted()); } } // Check any-of rules (OR-combined rules) @@ -258,12 +258,12 @@ abstract contract RuleBasedGroup is IGroup, RuleBasedPrimitive { ) { ruleParams = rulesProcessingParams[j].ruleParams; } - (bool callNotReverted,) = encodeAndCall( - rule.ruleAddress, rule.configSalt, originalMsgSender, account, primitiveCustomParams, ruleParams - ); - if (callNotReverted) { - return; // If any of the OR-combined rules passed, it means they succeed and we can return - } + // (bool callNotReverted,) = encodeAndCall( + // rule.ruleAddress, rule.configSalt, originalMsgSender, account, primitiveCustomParams, ruleParams + // ); + // if (callNotReverted) { + // return; // If any of the OR-combined rules passed, it means they succeed and we can return + // } } } // If there are any-of rules and it reached this point, it means all of them failed. diff --git a/contracts/core/primitives/namespace/Namespace.sol b/contracts/core/primitives/namespace/Namespace.sol index 67ce98df..03a72144 100644 --- a/contracts/core/primitives/namespace/Namespace.sol +++ b/contracts/core/primitives/namespace/Namespace.sol @@ -100,22 +100,22 @@ contract Namespace is KeyValue[] calldata customParams, RuleProcessingParams[] calldata unassigningProcessingParams, RuleProcessingParams[] calldata creationProcessingParams, - RuleProcessingParams[] calldata assigningProcessingParams, + RuleProcessingParams[] memory assigningProcessingParams, KeyValue[] memory extraData ) external { - require(msg.sender == account, Errors.InvalidMsgSender()); - uint256 id = _computeId(username); - _safeMint(account, id); - _idToUsername[id] = username; - Core._createUsername(username); - address source = _processSourceStamp(id, customParams); - _decodeAndSetUsernameExtraData(id, extraData); - emit Lens_Username_Created(username, account, customParams, creationProcessingParams, source, extraData); - _unassignIfAssigned(account, customParams, unassigningProcessingParams, source); - Core._assignUsername(account, username); - emit Lens_Username_Assigned(username, account, customParams, assigningProcessingParams, source); - _processCreation(msg.sender, account, username, customParams, creationProcessingParams); - _processAssigning(msg.sender, account, username, customParams, assigningProcessingParams); + // require(msg.sender == account, Errors.InvalidMsgSender()); + // uint256 id = _computeId(username); + // _safeMint(account, id); + // _idToUsername[id] = username; + // Core._createUsername(username); + // address source = _processSourceStamp(id, customParams); + // _decodeAndSetUsernameExtraData(id, extraData); + // emit Lens_Username_Created(username, account, customParams, creationProcessingParams, source, extraData); + // _unassignIfAssigned(account, customParams, unassigningProcessingParams, source); + // Core._assignUsername(account, username); + // emit Lens_Username_Assigned(username, account, customParams, assigningProcessingParams, source); + // _processCreation(msg.sender, account, username, customParams, creationProcessingParams); + // _processAssigning(msg.sender, account, username, customParams, assigningProcessingParams); } function createUsername( diff --git a/contracts/core/primitives/namespace/RuleBasedNamespace.sol b/contracts/core/primitives/namespace/RuleBasedNamespace.sol index 6aaa08ba..0ed78dcf 100644 --- a/contracts/core/primitives/namespace/RuleBasedNamespace.sol +++ b/contracts/core/primitives/namespace/RuleBasedNamespace.sol @@ -259,16 +259,16 @@ abstract contract RuleBasedNamespace is INamespace, RuleBasedPrimitive { ) { ruleParams = rulesProcessingParams[j].ruleParams; } - (bool callNotReverted,) = encodeAndCall( - rule.ruleAddress, - rule.configSalt, - originalMsgSender, - account, - username, - primitiveCustomParams, - ruleParams - ); - require(callNotReverted, Errors.RequiredRuleReverted()); + // (bool callNotReverted,) = encodeAndCall( + // rule.ruleAddress, + // rule.configSalt, + // originalMsgSender, + // account, + // username, + // primitiveCustomParams, + // ruleParams + // ); + // require(callNotReverted, Errors.RequiredRuleReverted()); } } // Check any-of rules (OR-combined rules) @@ -282,18 +282,18 @@ abstract contract RuleBasedNamespace is INamespace, RuleBasedPrimitive { ) { ruleParams = rulesProcessingParams[j].ruleParams; } - (bool callNotReverted,) = encodeAndCall( - rule.ruleAddress, - rule.configSalt, - originalMsgSender, - account, - username, - primitiveCustomParams, - ruleParams - ); - if (callNotReverted) { - return; // If any of the OR-combined rules passed, it means they succeed and we can return - } + // (bool callNotReverted,) = encodeAndCall( + // rule.ruleAddress, + // rule.configSalt, + // originalMsgSender, + // account, + // username, + // primitiveCustomParams, + // ruleParams + // ); + // if (callNotReverted) { + // return; // If any of the OR-combined rules passed, it means they succeed and we can return + // } } } // If there are any-of rules and it reached this point, it means all of them failed. diff --git a/contracts/extensions/factories/LensFactory.sol b/contracts/extensions/factories/LensFactory.sol index 33ed6e71..bece1ccb 100644 --- a/contracts/extensions/factories/LensFactory.sol +++ b/contracts/extensions/factories/LensFactory.sol @@ -87,114 +87,114 @@ contract LensFactory { GROUP_GATED_FEED_RULE = groupGatedFeedRule; } - // TODO: This function belongs to an App probably. - function createAccountWithUsernameFree( - string calldata metadataURI, - address owner, - address[] calldata accountManagers, - AccountManagerPermissions[] calldata accountManagersPermissions, - address namespacePrimitiveAddress, - string calldata username, - SourceStamp calldata accountCreationSourceStamp, - KeyValue[] calldata createUsernameCustomParams, - RuleProcessingParams[] calldata createUsernameRuleProcessingParams, - KeyValue[] calldata assignUsernameCustomParams, - RuleProcessingParams[] calldata unassignAccountRuleProcessingParams, - RuleProcessingParams[] calldata assignRuleProcessingParams, - KeyValue[] calldata accountExtraData, - KeyValue[] calldata usernameExtraData - ) external returns (address) { - address account = ACCOUNT_FACTORY.deployAccount( - address(this), - metadataURI, - accountManagers, - accountManagersPermissions, - accountCreationSourceStamp, - accountExtraData - ); - INamespace namespacePrimitive = INamespace(namespacePrimitiveAddress); - bytes memory txData = abi.encodeCall( - namespacePrimitive.createUsername, - (account, username, createUsernameCustomParams, createUsernameRuleProcessingParams, usernameExtraData) - ); - IAccount(payable(account)).executeTransaction(namespacePrimitiveAddress, uint256(0), txData); - txData = abi.encodeCall( - namespacePrimitive.assignUsername, - ( - account, - username, - assignUsernameCustomParams, - unassignAccountRuleProcessingParams, - new RuleProcessingParams[](0), - assignRuleProcessingParams - ) - ); - IAccount(payable(account)).executeTransaction(namespacePrimitiveAddress, uint256(0), txData); - IOwnable(account).transferOwnership(owner); - return account; - } + // // TODO: This function belongs to an App probably. + // function createAccountWithUsernameFree( + // string calldata metadataURI, + // address owner, + // address[] calldata accountManagers, + // AccountManagerPermissions[] calldata accountManagersPermissions, + // address namespacePrimitiveAddress, + // string calldata username, + // SourceStamp calldata accountCreationSourceStamp, + // KeyValue[] calldata createUsernameCustomParams, + // RuleProcessingParams[] calldata createUsernameRuleProcessingParams, + // KeyValue[] calldata assignUsernameCustomParams, + // RuleProcessingParams[] calldata unassignAccountRuleProcessingParams, + // RuleProcessingParams[] calldata assignRuleProcessingParams, + // KeyValue[] calldata accountExtraData, + // KeyValue[] calldata usernameExtraData + // ) external returns (address) { + // address account = ACCOUNT_FACTORY.deployAccount( + // address(this), + // metadataURI, + // accountManagers, + // accountManagersPermissions, + // accountCreationSourceStamp, + // accountExtraData + // ); + // INamespace namespacePrimitive = INamespace(namespacePrimitiveAddress); + // bytes memory txData = abi.encodeCall( + // namespacePrimitive.createUsername, + // (account, username, createUsernameCustomParams, createUsernameRuleProcessingParams, usernameExtraData) + // ); + // IAccount(payable(account)).executeTransaction(namespacePrimitiveAddress, uint256(0), txData); + // txData = abi.encodeCall( + // namespacePrimitive.assignUsername, + // ( + // account, + // username, + // assignUsernameCustomParams, + // unassignAccountRuleProcessingParams, + // new RuleProcessingParams[](0), + // assignRuleProcessingParams + // ) + // ); + // IAccount(payable(account)).executeTransaction(namespacePrimitiveAddress, uint256(0), txData); + // IOwnable(account).transferOwnership(owner); + // return account; + // } - function createGroupWithFeed( - address owner, - address[] calldata admins, - string calldata groupMetadataURI, - RuleChange[] calldata groupRules, - KeyValue[] calldata groupExtraData, - string calldata feedMetadataURI, - RuleChange[] calldata feedRules, - KeyValue[] calldata feedExtraData - ) external returns (address, address) { - IRoleBasedAccessControl groupAccessControl = _deployAccessControl(owner, admins); + // function createGroupWithFeed( + // address owner, + // address[] calldata admins, + // string calldata groupMetadataURI, + // RuleChange[] calldata groupRules, + // KeyValue[] calldata groupExtraData, + // string calldata feedMetadataURI, + // RuleChange[] calldata feedRules, + // KeyValue[] calldata feedExtraData + // ) external returns (address, address) { + // IRoleBasedAccessControl groupAccessControl = _deployAccessControl(owner, admins); - address group = GROUP_FACTORY.deployGroup( - groupMetadataURI, - TEMPORARY_ACCESS_CONTROL, - owner, - _injectRuleAccessControl(groupRules, address(groupAccessControl)), - groupExtraData - ); + // address group = GROUP_FACTORY.deployGroup( + // groupMetadataURI, + // TEMPORARY_ACCESS_CONTROL, + // owner, + // _injectRuleAccessControl(groupRules, address(groupAccessControl)), + // groupExtraData + // ); - RuleChange[] memory modifiedFeedRules = new RuleChange[](feedRules.length + 2); + // RuleChange[] memory modifiedFeedRules = new RuleChange[](feedRules.length + 2); - RuleSelectorChange[] memory selectorChanges = new RuleSelectorChange[](1); - // Both rules only operate on IFeedRule.processCreatePost.selector (at least at the moment of writing this) - selectorChanges[0] = - RuleSelectorChange({ruleSelector: IFeedRule.processCreatePost.selector, isRequired: true, enabled: true}); + // RuleSelectorChange[] memory selectorChanges = new RuleSelectorChange[](1); + // // Both rules only operate on IFeedRule.processCreatePost.selector (at least at the moment of writing this) + // selectorChanges[0] = + // RuleSelectorChange({ruleSelector: IFeedRule.processCreatePost.selector, isRequired: true, enabled: true}); - modifiedFeedRules[0] = RuleChange({ - ruleAddress: ACCOUNT_BLOCKING_RULE, - configSalt: bytes32(0), - configurationChanges: RuleConfigurationChange({configure: true, ruleParams: new KeyValue[](0)}), - selectorChanges: selectorChanges - }); + // modifiedFeedRules[0] = RuleChange({ + // ruleAddress: ACCOUNT_BLOCKING_RULE, + // configSalt: bytes32(0), + // configurationChanges: RuleConfigurationChange({configure: true, ruleParams: new KeyValue[](0)}), + // selectorChanges: selectorChanges + // }); - KeyValue[] memory groupGatedRuleParams = new KeyValue[](1); - groupGatedRuleParams[0] = KeyValue({key: PARAM__GROUP, value: abi.encode(group)}); + // KeyValue[] memory groupGatedRuleParams = new KeyValue[](1); + // groupGatedRuleParams[0] = KeyValue({key: PARAM__GROUP, value: abi.encode(group)}); - modifiedFeedRules[1] = RuleChange({ - ruleAddress: GROUP_GATED_FEED_RULE, - configSalt: bytes32(0), - configurationChanges: RuleConfigurationChange({configure: true, ruleParams: groupGatedRuleParams}), - selectorChanges: selectorChanges - }); + // modifiedFeedRules[1] = RuleChange({ + // ruleAddress: GROUP_GATED_FEED_RULE, + // configSalt: bytes32(0), + // configurationChanges: RuleConfigurationChange({configure: true, ruleParams: groupGatedRuleParams}), + // selectorChanges: selectorChanges + // }); - IRoleBasedAccessControl feedAccessControl = _deployAccessControl(owner, admins); + // IRoleBasedAccessControl feedAccessControl = _deployAccessControl(owner, admins); - for (uint256 i = 0; i < feedRules.length; i++) { - require(feedRules[i].ruleAddress != ACCOUNT_BLOCKING_RULE, Errors.DuplicatedValue()); - require(feedRules[i].ruleAddress != GROUP_GATED_FEED_RULE, Errors.DuplicatedValue()); - modifiedFeedRules[i + 2] = _injectRuleAccessControl(feedRules[i], address(feedAccessControl)); - } + // for (uint256 i = 0; i < feedRules.length; i++) { + // require(feedRules[i].ruleAddress != ACCOUNT_BLOCKING_RULE, Errors.DuplicatedValue()); + // require(feedRules[i].ruleAddress != GROUP_GATED_FEED_RULE, Errors.DuplicatedValue()); + // modifiedFeedRules[i + 2] = _injectRuleAccessControl(feedRules[i], address(feedAccessControl)); + // } - address feed = - FEED_FACTORY.deployFeed(feedMetadataURI, feedAccessControl, owner, modifiedFeedRules, feedExtraData); + // address feed = + // FEED_FACTORY.deployFeed(feedMetadataURI, feedAccessControl, owner, modifiedFeedRules, feedExtraData); - KeyValue[] memory groupExtraDataWithFeed = new KeyValue[](1); - groupExtraDataWithFeed[0] = KeyValue({key: DATA__GROUP_LINKED_FEED, value: abi.encode(feed)}); - IGroup(group).setExtraData(groupExtraDataWithFeed); - AccessControlled(group).setAccessControl(groupAccessControl); - return (group, feed); - } + // KeyValue[] memory groupExtraDataWithFeed = new KeyValue[](1); + // groupExtraDataWithFeed[0] = KeyValue({key: DATA__GROUP_LINKED_FEED, value: abi.encode(feed)}); + // IGroup(group).setExtraData(groupExtraDataWithFeed); + // AccessControlled(group).setAccessControl(groupAccessControl); + // return (group, feed); + // } function deployAccount( string calldata metadataURI, @@ -274,30 +274,30 @@ contract LensFactory { ); } - function deployNamespace( - string calldata namespace, - string calldata metadataURI, - address owner, - address[] calldata admins, - RuleChange[] calldata rules, - KeyValue[] calldata extraData, - string calldata nftName, - string calldata nftSymbol - ) external returns (address) { - ITokenURIProvider tokenURIProvider = new LensUsernameTokenURIProvider(); - IRoleBasedAccessControl accessControl = _deployAccessControl(owner, admins); - return NAMESPACE_FACTORY.deployNamespace( - namespace, - metadataURI, - accessControl, - owner, - _injectRuleAccessControl(rules, address(accessControl)), - extraData, - nftName, - nftSymbol, - tokenURIProvider - ); - } + // function deployNamespace( + // string calldata namespace, + // string calldata metadataURI, + // address owner, + // address[] calldata admins, + // RuleChange[] calldata rules, + // KeyValue[] calldata extraData, + // string calldata nftName, + // string calldata nftSymbol + // ) external returns (address) { + // ITokenURIProvider tokenURIProvider = new LensUsernameTokenURIProvider(); + // IRoleBasedAccessControl accessControl = _deployAccessControl(owner, admins); + // return NAMESPACE_FACTORY.deployNamespace( + // namespace, + // metadataURI, + // accessControl, + // owner, + // _injectRuleAccessControl(rules, address(accessControl)), + // extraData, + // nftName, + // nftSymbol, + // tokenURIProvider + // ); + // } function _deployAccessControl(address owner, address[] calldata admins) internal returns (IRoleBasedAccessControl) { return ACCESS_CONTROL_FACTORY.deployOwnerAdminOnlyAccessControl(owner, admins); diff --git a/contracts/migration/MigrationFeed.sol b/contracts/migration/MigrationFeed.sol index f469e4f3..82e51cea 100644 --- a/contracts/migration/MigrationFeed.sol +++ b/contracts/migration/MigrationFeed.sol @@ -24,11 +24,11 @@ contract MigrationFeed is Feed { uint80 creationTimestamp, address source ) = abi.decode(customParams[0].value, (uint256, uint256, uint256, uint256, uint80, address)); - _createPost(postParams, postId, rootPostId, postSequentialId, authorPostSequentialId, creationTimestamp); + // _createPost(postParams, postId, rootPostId, postSequentialId, authorPostSequentialId, creationTimestamp); if (customParams.length > 1 && abi.decode(customParams[1].value, (bool))) { // If customParams[1] is present, it must be an ABI-encoded bool representing `forceChecks` - _forceChecks(postId, rootPostId, postParams); + // _forceChecks(postId, rootPostId, postParams); } if (source != address(0)) { @@ -37,25 +37,25 @@ contract MigrationFeed is Feed { _setPrimitiveInternalExtraDataForEntity(postId, KeyValue(DATA__LAST_UPDATED_SOURCE, abi.encode(source))); } - emit Lens_Feed_PostCreated( - postId, - postParams.author, - authorPostSequentialId, - rootPostId, - postParams, - customParams, - feedRulesParams, - rootPostRulesParams, - quotedPostRulesParams, - source - ); + // emit Lens_Feed_PostCreated( + // source, + // postId, + // authorPostSequentialId, + // rootPostId, + // quotedPostRulesParams, + // rootPostRulesParams, + // feedRulesParams, + // customParams, + // postParams, + // postParams.author + // ); - for (uint256 i = 0; i < postParams.extraData.length; i++) { - _setEntityExtraData(postId, postParams.extraData[i]); - emit Lens_Feed_Post_ExtraDataAdded( - postId, postParams.extraData[i].key, postParams.extraData[i].value, postParams.extraData[i].value - ); - } + // for (uint256 i = 0; i < postParams.extraData.length; i++) { + // _setEntityExtraData(postId, postParams.extraData[i]); + // emit Lens_Feed_Post_ExtraDataAdded( + // postId, postParams.extraData[i].key, postParams.extraData[i].value, postParams.extraData[i].value + // ); + // } return postId; } diff --git a/foundry.toml b/foundry.toml index 56a7e71a..9c6d9180 100644 --- a/foundry.toml +++ b/foundry.toml @@ -5,6 +5,9 @@ libs = ['node_modules', 'lib'] test = 'test' cache_path = 'cache_forge' solc_version = '0.8.28' +# via_ir = true +optimizer = false +# optimizer_runs = 10 [profile.default.fuzz] runs = 1024 @@ -12,9 +15,9 @@ no_zksync_reserved_addresses = true [profile.default.zksync] # Compile contracts for zkVM -compile = true +# compile = true # Enable zkVM at startup, needs `compile = true` to have effect -startup = true +# startup = true # # By default the latest version is used # zksolc = "1.5.0" # # By default the corresponding solc patched version from matter-labs is used diff --git a/test/factories/LensFactory.t.sol b/test/factories/LensFactory.t.sol index d079b561..3d6fdba6 100644 --- a/test/factories/LensFactory.t.sol +++ b/test/factories/LensFactory.t.sol @@ -25,18 +25,18 @@ contract LensFactoryTest is Test, BaseDeployments { function setUp() public override { super.setUp(); - namespace = Namespace( - lensFactory.deployNamespace({ - namespace: "bitcoin", - metadataURI: "satoshi://nakamoto", - owner: address(this), - admins: new address[](0), - rules: new RuleChange[](0), - extraData: new KeyValue[](0), - nftName: "Bitcoin", - nftSymbol: "BTC" - }) - ); + // namespace = Namespace( + // lensFactory.deployNamespace({ + // namespace: "bitcoin", + // metadataURI: "satoshi://nakamoto", + // owner: address(this), + // admins: new address[](0), + // rules: new RuleChange[](0), + // extraData: new KeyValue[](0), + // nftName: "Bitcoin", + // nftSymbol: "BTC" + // }) + // ); } function testCanDeployFeed() public { @@ -50,22 +50,22 @@ contract LensFactoryTest is Test, BaseDeployments { } function testCreateAccountWithUsernameFree() public { - lensFactory.createAccountWithUsernameFree({ - metadataURI: "someMetadataURI", - owner: address(this), - accountManagers: _emptyAddressArray(), - accountManagersPermissions: new AccountManagerPermissions[](0), - namespacePrimitiveAddress: address(namespace), - username: "myTestUsername", - accountCreationSourceStamp: _emptySourceStamp(), - createUsernameCustomParams: _emptyKeyValueArray(), - createUsernameRuleProcessingParams: _emptyRuleProcessingParamsArray(), - assignUsernameCustomParams: _emptyKeyValueArray(), - unassignAccountRuleProcessingParams: _emptyRuleProcessingParamsArray(), - assignRuleProcessingParams: _emptyRuleProcessingParamsArray(), - accountExtraData: _emptyKeyValueArray(), - usernameExtraData: _emptyKeyValueArray() - }); + // lensFactory.createAccountWithUsernameFree({ + // metadataURI: "someMetadataURI", + // owner: address(this), + // accountManagers: _emptyAddressArray(), + // accountManagersPermissions: new AccountManagerPermissions[](0), + // namespacePrimitiveAddress: address(namespace), + // username: "myTestUsername", + // accountCreationSourceStamp: _emptySourceStamp(), + // createUsernameCustomParams: _emptyKeyValueArray(), + // createUsernameRuleProcessingParams: _emptyRuleProcessingParamsArray(), + // assignUsernameCustomParams: _emptyKeyValueArray(), + // unassignAccountRuleProcessingParams: _emptyRuleProcessingParamsArray(), + // assignRuleProcessingParams: _emptyRuleProcessingParamsArray(), + // accountExtraData: _emptyKeyValueArray(), + // usernameExtraData: _emptyKeyValueArray() + // }); } function testGraphFollowWithFactorySetup() public { diff --git a/test/primitives/Namespace.t.sol b/test/primitives/Namespace.t.sol index 9e097c7e..32b4f1a2 100644 --- a/test/primitives/Namespace.t.sol +++ b/test/primitives/Namespace.t.sol @@ -20,18 +20,18 @@ contract NamespaceTest is Test, BaseDeployments { function setUp() public override { super.setUp(); - namespace = INamespace( - lensFactory.deployNamespace({ - namespace: "bitcoin", - metadataURI: "satoshi://nakamoto", - owner: namespaceOwner, - admins: _emptyAddressArray(), - rules: _emptyRuleChangeArray(), - extraData: _emptyKeyValueArray(), - nftName: "Bitcoin", - nftSymbol: "BTC" - }) - ); + // namespace = INamespace( + // lensFactory.deployNamespace({ + // namespace: "bitcoin", + // metadataURI: "satoshi://nakamoto", + // owner: namespaceOwner, + // admins: _emptyAddressArray(), + // rules: _emptyRuleChangeArray(), + // extraData: _emptyKeyValueArray(), + // nftName: "Bitcoin", + // nftSymbol: "BTC" + // }) + // ); } function testCreateAssignUnassignDelete() public { From 5873156f7ac14d8f0a645d79ec4a3bd5079b7316 Mon Sep 17 00:00:00 2001 From: vicnaum Date: Thu, 9 Jan 2025 20:54:26 +0100 Subject: [PATCH 07/41] misc: Namespaces and Graph compile without IR --- .../core/primitives/graph/RuleBasedGraph.sol | 220 +++++++----------- .../core/primitives/namespace/Namespace.sol | 28 +-- .../namespace/RuleBasedNamespace.sol | 206 ++++++++-------- .../extensions/factories/LensFactory.sol | 50 ++-- test/factories/LensFactory.t.sol | 24 +- test/primitives/Namespace.t.sol | 24 +- 6 files changed, 260 insertions(+), 292 deletions(-) diff --git a/contracts/core/primitives/graph/RuleBasedGraph.sol b/contracts/core/primitives/graph/RuleBasedGraph.sol index 7158d81f..ea02f760 100644 --- a/contracts/core/primitives/graph/RuleBasedGraph.sol +++ b/contracts/core/primitives/graph/RuleBasedGraph.sol @@ -180,24 +180,28 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive { require($graphRulesStorage().anyOfRules[ruleSelector].length == 0, Errors.AllAnyOfRulesReverted()); } + struct ProcessParams { + address originalMsgSender; + address sourceAccount; + address targetAccount; + KeyValue[] primitiveCustomParams; + RuleProcessingParams[] rulesProcessingParams; + } + function _encodeAndCallGraphProcessFollow( - address rule, - bytes32 configSalt, - address originalMsgSender, - address followerAccount, - address accountToFollow, - KeyValue[] calldata primitiveCustomParams, + Rule memory rule, + ProcessParams memory processParams, KeyValue[] memory ruleCustomParams ) internal returns (bool, bytes memory) { - return rule.safecall( + return rule.ruleAddress.safecall( abi.encodeCall( IGraphRule.processFollow, ( - configSalt, - originalMsgSender, - followerAccount, - accountToFollow, - primitiveCustomParams, + rule.configSalt, + processParams.originalMsgSender, + processParams.sourceAccount, + processParams.targetAccount, + processParams.primitiveCustomParams, ruleCustomParams ) ) @@ -209,38 +213,36 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive { address followerAccount, address accountToFollow, KeyValue[] calldata primitiveCustomParams, - RuleProcessingParams[] calldata ruleProcessingParams + RuleProcessingParams[] calldata rulesProcessingParams ) internal { _processFollow( $graphRulesStorage(), _encodeAndCallGraphProcessFollow, IGraphRule.processFollow.selector, - originalMsgSender, - followerAccount, - accountToFollow, - primitiveCustomParams, - ruleProcessingParams + ProcessParams({ + originalMsgSender: originalMsgSender, + sourceAccount: followerAccount, + targetAccount: accountToFollow, + primitiveCustomParams: primitiveCustomParams, + rulesProcessingParams: rulesProcessingParams + }) ); } function _encodeAndCallGraphProcessUnfollow( - address rule, - bytes32 configSalt, - address originalMsgSender, - address followerAccount, - address accountToUnfollow, - KeyValue[] calldata primitiveCustomParams, + Rule memory rule, + ProcessParams memory processParams, KeyValue[] memory ruleCustomParams ) internal returns (bool, bytes memory) { - return rule.safecall( + return rule.ruleAddress.safecall( abi.encodeCall( IGraphRule.processUnfollow, ( - configSalt, - originalMsgSender, - followerAccount, - accountToUnfollow, - primitiveCustomParams, + rule.configSalt, + processParams.originalMsgSender, + processParams.sourceAccount, + processParams.targetAccount, + processParams.primitiveCustomParams, ruleCustomParams ) ) @@ -252,37 +254,35 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive { address followerAccount, address accountToUnfollow, KeyValue[] calldata primitiveCustomParams, - RuleProcessingParams[] calldata ruleProcessingParams + RuleProcessingParams[] calldata rulesProcessingParams ) internal { _processUnfollow( $graphRulesStorage(), _encodeAndCallGraphProcessUnfollow, - originalMsgSender, - followerAccount, - accountToUnfollow, - primitiveCustomParams, - ruleProcessingParams + ProcessParams({ + originalMsgSender: originalMsgSender, + sourceAccount: followerAccount, + targetAccount: accountToUnfollow, + primitiveCustomParams: primitiveCustomParams, + rulesProcessingParams: rulesProcessingParams + }) ); } function _encodeAndCallAccountProcessFollow( - address rule, - bytes32 configSalt, - address originalMsgSender, - address followerAccount, - address accountToFollow, - KeyValue[] calldata primitiveCustomParams, + Rule memory rule, + ProcessParams memory processParams, KeyValue[] memory ruleCustomParams ) internal returns (bool, bytes memory) { - return rule.safecall( + return rule.ruleAddress.safecall( abi.encodeCall( IFollowRule.processFollow, ( - configSalt, - originalMsgSender, - followerAccount, - accountToFollow, - primitiveCustomParams, + rule.configSalt, + processParams.originalMsgSender, + processParams.sourceAccount, + processParams.targetAccount, + processParams.primitiveCustomParams, ruleCustomParams ) ) @@ -294,143 +294,103 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive { address followerAccount, address accountToFollow, KeyValue[] calldata primitiveCustomParams, - RuleProcessingParams[] calldata ruleProcessingParams + RuleProcessingParams[] calldata rulesProcessingParams ) internal { _processFollow( $followRulesStorage(accountToFollow), _encodeAndCallAccountProcessFollow, IFollowRule.processFollow.selector, - originalMsgSender, - followerAccount, - accountToFollow, - primitiveCustomParams, - ruleProcessingParams + ProcessParams({ + originalMsgSender: originalMsgSender, + sourceAccount: followerAccount, + targetAccount: accountToFollow, + primitiveCustomParams: primitiveCustomParams, + rulesProcessingParams: rulesProcessingParams + }) ); } function _processUnfollow( RulesStorage storage rulesStorage, - function(address,bytes32,address,address,address,KeyValue[] calldata,KeyValue[] memory) internal returns (bool,bytes memory) - encodeAndCall, - address originalMsgSender, - address followerAccount, - address accountToUnfollow, - KeyValue[] calldata primitiveCustomParams, - RuleProcessingParams[] calldata rulesProcessingParams + function(Rule memory,ProcessParams memory,KeyValue[] memory) internal returns (bool,bytes memory) encodeAndCall, + ProcessParams memory processParams ) internal { bytes4 ruleSelector = IGraphRule.processUnfollow.selector; // Check required rules (AND-combined rules) for (uint256 i = 0; i < rulesStorage.requiredRules[ruleSelector].length; i++) { Rule memory rule = rulesStorage.requiredRules[ruleSelector][i]; // TODO: Think how to put this loop into a library (all the rules use it) - for (uint256 j = 0; j < rulesProcessingParams.length; j++) { + for (uint256 j = 0; j < processParams.rulesProcessingParams.length; j++) { KeyValue[] memory ruleCustomParams = new KeyValue[](0); if ( - rulesProcessingParams[j].ruleAddress == rule.ruleAddress - && rulesProcessingParams[j].configSalt == rule.configSalt + processParams.rulesProcessingParams[j].ruleAddress == rule.ruleAddress + && processParams.rulesProcessingParams[j].configSalt == rule.configSalt ) { - ruleCustomParams = rulesProcessingParams[j].ruleParams; + ruleCustomParams = processParams.rulesProcessingParams[j].ruleParams; } - // (bool callNotReverted,) = encodeAndCall( - // rule.ruleAddress, - // rule.configSalt, - // originalMsgSender, - // followerAccount, - // accountToUnfollow, - // primitiveCustomParams, - // ruleCustomParams - // ); - // require(callNotReverted, Errors.RequiredRuleReverted()); + (bool callNotReverted,) = encodeAndCall(rule, processParams, ruleCustomParams); + require(callNotReverted, Errors.RequiredRuleReverted()); } } for (uint256 i = 0; i < rulesStorage.anyOfRules[ruleSelector].length; i++) { Rule memory rule = rulesStorage.anyOfRules[ruleSelector][i]; - for (uint256 j = 0; j < rulesProcessingParams.length; j++) { + for (uint256 j = 0; j < processParams.rulesProcessingParams.length; j++) { KeyValue[] memory ruleCustomParams = new KeyValue[](0); if ( - rulesProcessingParams[j].ruleAddress == rule.ruleAddress - && rulesProcessingParams[j].configSalt == rule.configSalt + processParams.rulesProcessingParams[j].ruleAddress == rule.ruleAddress + && processParams.rulesProcessingParams[j].configSalt == rule.configSalt ) { - ruleCustomParams = rulesProcessingParams[j].ruleParams; + ruleCustomParams = processParams.rulesProcessingParams[j].ruleParams; + } + (bool callNotReverted,) = encodeAndCall(rule, processParams, ruleCustomParams); + if (callNotReverted) { + return; // If any of the OR-combined rules passed, it means they succeed and we can return } - // (bool callNotReverted,) = encodeAndCall( - // rule.ruleAddress, - // rule.configSalt, - // originalMsgSender, - // followerAccount, - // accountToUnfollow, - // primitiveCustomParams, - // ruleCustomParams - // ); - // if (callNotReverted) { - // return; // If any of the OR-combined rules passed, it means they succeed and we can return - // } } } // If there are any-of rules and it reached this point, it means all of them failed. - require($graphRulesStorage().anyOfRules[ruleSelector].length == 0, Errors.AllAnyOfRulesReverted()); + require(rulesStorage.anyOfRules[ruleSelector].length == 0, Errors.AllAnyOfRulesReverted()); } function _processFollow( RulesStorage storage rulesStorage, - function(address,bytes32,address,address,address,KeyValue[] calldata,KeyValue[] memory) internal returns (bool,bytes memory) - encodeAndCall, + function(Rule memory,ProcessParams memory,KeyValue[] memory) internal returns (bool,bytes memory) encodeAndCall, bytes4 ruleSelector, - address originalMsgSender, - address followerAccount, - address accountToFollow, - KeyValue[] calldata primitiveCustomParams, - RuleProcessingParams[] calldata rulesProcessingParams + ProcessParams memory processParams ) internal { // Check required rules (AND-combined rules) for (uint256 i = 0; i < rulesStorage.requiredRules[ruleSelector].length; i++) { Rule memory rule = rulesStorage.requiredRules[ruleSelector][i]; // TODO: Think how to put this loop into a library (all the rules use it) - for (uint256 j = 0; j < rulesProcessingParams.length; j++) { + for (uint256 j = 0; j < processParams.rulesProcessingParams.length; j++) { KeyValue[] memory ruleCustomParams = new KeyValue[](0); if ( - rulesProcessingParams[j].ruleAddress == rule.ruleAddress - && rulesProcessingParams[j].configSalt == rule.configSalt + processParams.rulesProcessingParams[j].ruleAddress == rule.ruleAddress + && processParams.rulesProcessingParams[j].configSalt == rule.configSalt ) { - ruleCustomParams = rulesProcessingParams[j].ruleParams; + ruleCustomParams = processParams.rulesProcessingParams[j].ruleParams; } - // (bool callNotReverted,) = encodeAndCall( - // rule.ruleAddress, - // rule.configSalt, - // originalMsgSender, - // followerAccount, - // accountToFollow, - // primitiveCustomParams, - // ruleCustomParams - // ); - // require(callNotReverted, Errors.RequiredRuleReverted()); + (bool callNotReverted,) = encodeAndCall(rule, processParams, ruleCustomParams); + require(callNotReverted, Errors.RequiredRuleReverted()); } } for (uint256 i = 0; i < rulesStorage.anyOfRules[ruleSelector].length; i++) { Rule memory rule = rulesStorage.anyOfRules[ruleSelector][i]; - for (uint256 j = 0; j < rulesProcessingParams.length; j++) { + for (uint256 j = 0; j < processParams.rulesProcessingParams.length; j++) { KeyValue[] memory ruleCustomParams = new KeyValue[](0); if ( - rulesProcessingParams[j].ruleAddress == rule.ruleAddress - && rulesProcessingParams[j].configSalt == rule.configSalt + processParams.rulesProcessingParams[j].ruleAddress == rule.ruleAddress + && processParams.rulesProcessingParams[j].configSalt == rule.configSalt ) { - ruleCustomParams = rulesProcessingParams[j].ruleParams; + ruleCustomParams = processParams.rulesProcessingParams[j].ruleParams; + } + (bool callNotReverted,) = encodeAndCall(rule, processParams, ruleCustomParams); + if (callNotReverted) { + return; // If any of the OR-combined rules passed, it means they succeed and we can return } - // (bool callNotReverted,) = encodeAndCall( - // rule.ruleAddress, - // rule.configSalt, - // originalMsgSender, - // followerAccount, - // accountToFollow, - // primitiveCustomParams, - // ruleCustomParams - // ); - // if (callNotReverted) { - // return; // If any of the OR-combined rules passed, it means they succeed and we can return - // } } } // If there are any-of rules and it reached this point, it means all of them failed. - require($graphRulesStorage().anyOfRules[ruleSelector].length == 0, Errors.AllAnyOfRulesReverted()); + require(rulesStorage.anyOfRules[ruleSelector].length == 0, Errors.AllAnyOfRulesReverted()); } } diff --git a/contracts/core/primitives/namespace/Namespace.sol b/contracts/core/primitives/namespace/Namespace.sol index 03a72144..67ce98df 100644 --- a/contracts/core/primitives/namespace/Namespace.sol +++ b/contracts/core/primitives/namespace/Namespace.sol @@ -100,22 +100,22 @@ contract Namespace is KeyValue[] calldata customParams, RuleProcessingParams[] calldata unassigningProcessingParams, RuleProcessingParams[] calldata creationProcessingParams, - RuleProcessingParams[] memory assigningProcessingParams, + RuleProcessingParams[] calldata assigningProcessingParams, KeyValue[] memory extraData ) external { - // require(msg.sender == account, Errors.InvalidMsgSender()); - // uint256 id = _computeId(username); - // _safeMint(account, id); - // _idToUsername[id] = username; - // Core._createUsername(username); - // address source = _processSourceStamp(id, customParams); - // _decodeAndSetUsernameExtraData(id, extraData); - // emit Lens_Username_Created(username, account, customParams, creationProcessingParams, source, extraData); - // _unassignIfAssigned(account, customParams, unassigningProcessingParams, source); - // Core._assignUsername(account, username); - // emit Lens_Username_Assigned(username, account, customParams, assigningProcessingParams, source); - // _processCreation(msg.sender, account, username, customParams, creationProcessingParams); - // _processAssigning(msg.sender, account, username, customParams, assigningProcessingParams); + require(msg.sender == account, Errors.InvalidMsgSender()); + uint256 id = _computeId(username); + _safeMint(account, id); + _idToUsername[id] = username; + Core._createUsername(username); + address source = _processSourceStamp(id, customParams); + _decodeAndSetUsernameExtraData(id, extraData); + emit Lens_Username_Created(username, account, customParams, creationProcessingParams, source, extraData); + _unassignIfAssigned(account, customParams, unassigningProcessingParams, source); + Core._assignUsername(account, username); + emit Lens_Username_Assigned(username, account, customParams, assigningProcessingParams, source); + _processCreation(msg.sender, account, username, customParams, creationProcessingParams); + _processAssigning(msg.sender, account, username, customParams, assigningProcessingParams); } function createUsername( diff --git a/contracts/core/primitives/namespace/RuleBasedNamespace.sol b/contracts/core/primitives/namespace/RuleBasedNamespace.sol index 0ed78dcf..9501a261 100644 --- a/contracts/core/primitives/namespace/RuleBasedNamespace.sol +++ b/contracts/core/primitives/namespace/RuleBasedNamespace.sol @@ -100,18 +100,21 @@ abstract contract RuleBasedNamespace is INamespace, RuleBasedPrimitive { //////////////////////////// PROCESSING FUNCTIONS //////////////////////////// function _encodeAndCallProcessCreation( - address rule, - bytes32 configSalt, - address originalMsgSender, - address account, - string memory username, - KeyValue[] calldata primitiveCustomParams, + Rule memory rule, + ProcessParams memory processParams, KeyValue[] memory ruleCustomParams ) internal returns (bool, bytes memory) { - return rule.safecall( + return rule.ruleAddress.safecall( abi.encodeCall( INamespaceRule.processCreation, - (configSalt, originalMsgSender, account, username, primitiveCustomParams, ruleCustomParams) + ( + rule.configSalt, + processParams.originalMsgSender, + processParams.account, + processParams.username, + processParams.primitiveCustomParams, + ruleCustomParams + ) ) ); } @@ -125,28 +128,32 @@ abstract contract RuleBasedNamespace is INamespace, RuleBasedPrimitive { ) internal { _processNamespaceRule( _encodeAndCallProcessCreation, - INamespaceRule.processCreation.selector, - originalMsgSender, - account, - username, - primitiveCustomParams, - rulesProcessingParams + ProcessParams({ + ruleSelector: INamespaceRule.processCreation.selector, + originalMsgSender: originalMsgSender, + account: account, + username: username, + primitiveCustomParams: primitiveCustomParams, + rulesProcessingParams: rulesProcessingParams + }) ); } function _encodeAndCallProcessRemoval( - address rule, - bytes32 configSalt, - address originalMsgSender, - address, /* account */ - string memory username, - KeyValue[] calldata primitiveCustomParams, + Rule memory rule, + ProcessParams memory processParams, KeyValue[] memory ruleCustomParams ) internal returns (bool, bytes memory) { - return rule.safecall( + return rule.ruleAddress.safecall( abi.encodeCall( INamespaceRule.processRemoval, - (configSalt, originalMsgSender, username, primitiveCustomParams, ruleCustomParams) + ( + rule.configSalt, + processParams.originalMsgSender, + processParams.username, + processParams.primitiveCustomParams, + ruleCustomParams + ) ) ); } @@ -159,28 +166,33 @@ abstract contract RuleBasedNamespace is INamespace, RuleBasedPrimitive { ) internal { _processNamespaceRule( _encodeAndCallProcessRemoval, - INamespaceRule.processRemoval.selector, - originalMsgSender, - address(0), - username, - primitiveCustomParams, - rulesProcessingParams + ProcessParams({ + ruleSelector: INamespaceRule.processRemoval.selector, + originalMsgSender: originalMsgSender, + account: address(0), + username: username, + primitiveCustomParams: primitiveCustomParams, + rulesProcessingParams: rulesProcessingParams + }) ); } function _encodeAndCallProcessAssigning( - address rule, - bytes32 configSalt, - address originalMsgSender, - address account, - string memory username, - KeyValue[] calldata primitiveCustomParams, + Rule memory rule, + ProcessParams memory processParams, KeyValue[] memory ruleCustomParams ) internal returns (bool, bytes memory) { - return rule.safecall( + return rule.ruleAddress.safecall( abi.encodeCall( INamespaceRule.processAssigning, - (configSalt, originalMsgSender, account, username, primitiveCustomParams, ruleCustomParams) + ( + rule.configSalt, + processParams.originalMsgSender, + processParams.account, + processParams.username, + processParams.primitiveCustomParams, + ruleCustomParams + ) ) ); } @@ -194,28 +206,33 @@ abstract contract RuleBasedNamespace is INamespace, RuleBasedPrimitive { ) internal { _processNamespaceRule( _encodeAndCallProcessAssigning, - INamespaceRule.processAssigning.selector, - originalMsgSender, - account, - username, - primitiveCustomParams, - rulesProcessingParams + ProcessParams({ + ruleSelector: INamespaceRule.processAssigning.selector, + originalMsgSender: originalMsgSender, + account: account, + username: username, + primitiveCustomParams: primitiveCustomParams, + rulesProcessingParams: rulesProcessingParams + }) ); } function _encodeAndCallProcessUnassigning( - address rule, - bytes32 configSalt, - address originalMsgSender, - address account, - string memory username, - KeyValue[] calldata primitiveCustomParams, + Rule memory rule, + ProcessParams memory processParams, KeyValue[] memory ruleCustomParams ) internal returns (bool, bytes memory) { - return rule.safecall( + return rule.ruleAddress.safecall( abi.encodeCall( INamespaceRule.processUnassigning, - (configSalt, originalMsgSender, account, username, primitiveCustomParams, ruleCustomParams) + ( + rule.configSalt, + processParams.originalMsgSender, + processParams.account, + processParams.username, + processParams.primitiveCustomParams, + ruleCustomParams + ) ) ); } @@ -229,74 +246,65 @@ abstract contract RuleBasedNamespace is INamespace, RuleBasedPrimitive { ) internal { _processNamespaceRule( _encodeAndCallProcessUnassigning, - INamespaceRule.processUnassigning.selector, - originalMsgSender, - account, - username, - primitiveCustomParams, - rulesProcessingParams + ProcessParams({ + ruleSelector: INamespaceRule.processUnassigning.selector, + originalMsgSender: originalMsgSender, + account: account, + username: username, + primitiveCustomParams: primitiveCustomParams, + rulesProcessingParams: rulesProcessingParams + }) ); } + struct ProcessParams { + bytes4 ruleSelector; + address originalMsgSender; + address account; + string username; + KeyValue[] primitiveCustomParams; + RuleProcessingParams[] rulesProcessingParams; + } + function _processNamespaceRule( - function(address,bytes32,address,address,string memory,KeyValue[] calldata,KeyValue[] memory) internal returns (bool,bytes memory) - encodeAndCall, - bytes4 ruleSelector, - address originalMsgSender, - address account, - string memory username, - KeyValue[] calldata primitiveCustomParams, - RuleProcessingParams[] calldata rulesProcessingParams + function(Rule memory,ProcessParams memory,KeyValue[] memory) internal returns (bool,bytes memory) encodeAndCall, + ProcessParams memory processParams ) private { // Check required rules (AND-combined rules) - for (uint256 i = 0; i < $namespaceRulesStorage().requiredRules[ruleSelector].length; i++) { - Rule memory rule = $namespaceRulesStorage().requiredRules[ruleSelector][i]; - for (uint256 j = 0; j < rulesProcessingParams.length; j++) { + for (uint256 i = 0; i < $namespaceRulesStorage().requiredRules[processParams.ruleSelector].length; i++) { + Rule memory rule = $namespaceRulesStorage().requiredRules[processParams.ruleSelector][i]; + for (uint256 j = 0; j < processParams.rulesProcessingParams.length; j++) { KeyValue[] memory ruleParams = new KeyValue[](0); if ( - rulesProcessingParams[j].ruleAddress == rule.ruleAddress - && rulesProcessingParams[j].configSalt == rule.configSalt + processParams.rulesProcessingParams[j].ruleAddress == rule.ruleAddress + && processParams.rulesProcessingParams[j].configSalt == rule.configSalt ) { - ruleParams = rulesProcessingParams[j].ruleParams; + ruleParams = processParams.rulesProcessingParams[j].ruleParams; } - // (bool callNotReverted,) = encodeAndCall( - // rule.ruleAddress, - // rule.configSalt, - // originalMsgSender, - // account, - // username, - // primitiveCustomParams, - // ruleParams - // ); - // require(callNotReverted, Errors.RequiredRuleReverted()); + (bool callNotReverted,) = encodeAndCall(rule, processParams, ruleParams); + require(callNotReverted, Errors.RequiredRuleReverted()); } } // Check any-of rules (OR-combined rules) - for (uint256 i = 0; i < $namespaceRulesStorage().anyOfRules[ruleSelector].length; i++) { - Rule memory rule = $namespaceRulesStorage().anyOfRules[ruleSelector][i]; - for (uint256 j = 0; j < rulesProcessingParams.length; j++) { + for (uint256 i = 0; i < $namespaceRulesStorage().anyOfRules[processParams.ruleSelector].length; i++) { + Rule memory rule = $namespaceRulesStorage().anyOfRules[processParams.ruleSelector][i]; + for (uint256 j = 0; j < processParams.rulesProcessingParams.length; j++) { KeyValue[] memory ruleParams = new KeyValue[](0); if ( - rulesProcessingParams[j].ruleAddress == rule.ruleAddress - && rulesProcessingParams[j].configSalt == rule.configSalt + processParams.rulesProcessingParams[j].ruleAddress == rule.ruleAddress + && processParams.rulesProcessingParams[j].configSalt == rule.configSalt ) { - ruleParams = rulesProcessingParams[j].ruleParams; + ruleParams = processParams.rulesProcessingParams[j].ruleParams; + } + (bool callNotReverted,) = encodeAndCall(rule, processParams, ruleParams); + if (callNotReverted) { + return; // If any of the OR-combined rules passed, it means they succeed and we can return } - // (bool callNotReverted,) = encodeAndCall( - // rule.ruleAddress, - // rule.configSalt, - // originalMsgSender, - // account, - // username, - // primitiveCustomParams, - // ruleParams - // ); - // if (callNotReverted) { - // return; // If any of the OR-combined rules passed, it means they succeed and we can return - // } } } // If there are any-of rules and it reached this point, it means all of them failed. - require($namespaceRulesStorage().anyOfRules[ruleSelector].length == 0, Errors.AllAnyOfRulesReverted()); + require( + $namespaceRulesStorage().anyOfRules[processParams.ruleSelector].length == 0, Errors.AllAnyOfRulesReverted() + ); } } diff --git a/contracts/extensions/factories/LensFactory.sol b/contracts/extensions/factories/LensFactory.sol index bece1ccb..eab6ef0b 100644 --- a/contracts/extensions/factories/LensFactory.sol +++ b/contracts/extensions/factories/LensFactory.sol @@ -274,32 +274,32 @@ contract LensFactory { ); } - // function deployNamespace( - // string calldata namespace, - // string calldata metadataURI, - // address owner, - // address[] calldata admins, - // RuleChange[] calldata rules, - // KeyValue[] calldata extraData, - // string calldata nftName, - // string calldata nftSymbol - // ) external returns (address) { - // ITokenURIProvider tokenURIProvider = new LensUsernameTokenURIProvider(); - // IRoleBasedAccessControl accessControl = _deployAccessControl(owner, admins); - // return NAMESPACE_FACTORY.deployNamespace( - // namespace, - // metadataURI, - // accessControl, - // owner, - // _injectRuleAccessControl(rules, address(accessControl)), - // extraData, - // nftName, - // nftSymbol, - // tokenURIProvider - // ); - // } + function deployNamespace( + string memory namespace, + string memory metadataURI, + address owner, + address[] memory admins, + RuleChange[] calldata rules, + KeyValue[] calldata extraData, + string memory nftName, + string memory nftSymbol + ) external returns (address) { + ITokenURIProvider tokenURIProvider = new LensUsernameTokenURIProvider(); + IRoleBasedAccessControl accessControl = _deployAccessControl(owner, admins); + return NAMESPACE_FACTORY.deployNamespace( + namespace, + metadataURI, + accessControl, + owner, + _injectRuleAccessControl(rules, address(accessControl)), + extraData, + nftName, + nftSymbol, + tokenURIProvider + ); + } - function _deployAccessControl(address owner, address[] calldata admins) internal returns (IRoleBasedAccessControl) { + function _deployAccessControl(address owner, address[] memory admins) internal returns (IRoleBasedAccessControl) { return ACCESS_CONTROL_FACTORY.deployOwnerAdminOnlyAccessControl(owner, admins); } diff --git a/test/factories/LensFactory.t.sol b/test/factories/LensFactory.t.sol index 3d6fdba6..50cd0b3d 100644 --- a/test/factories/LensFactory.t.sol +++ b/test/factories/LensFactory.t.sol @@ -25,18 +25,18 @@ contract LensFactoryTest is Test, BaseDeployments { function setUp() public override { super.setUp(); - // namespace = Namespace( - // lensFactory.deployNamespace({ - // namespace: "bitcoin", - // metadataURI: "satoshi://nakamoto", - // owner: address(this), - // admins: new address[](0), - // rules: new RuleChange[](0), - // extraData: new KeyValue[](0), - // nftName: "Bitcoin", - // nftSymbol: "BTC" - // }) - // ); + namespace = Namespace( + lensFactory.deployNamespace({ + namespace: "bitcoin", + metadataURI: "satoshi://nakamoto", + owner: address(this), + admins: new address[](0), + rules: new RuleChange[](0), + extraData: new KeyValue[](0), + nftName: "Bitcoin", + nftSymbol: "BTC" + }) + ); } function testCanDeployFeed() public { diff --git a/test/primitives/Namespace.t.sol b/test/primitives/Namespace.t.sol index 32b4f1a2..9e097c7e 100644 --- a/test/primitives/Namespace.t.sol +++ b/test/primitives/Namespace.t.sol @@ -20,18 +20,18 @@ contract NamespaceTest is Test, BaseDeployments { function setUp() public override { super.setUp(); - // namespace = INamespace( - // lensFactory.deployNamespace({ - // namespace: "bitcoin", - // metadataURI: "satoshi://nakamoto", - // owner: namespaceOwner, - // admins: _emptyAddressArray(), - // rules: _emptyRuleChangeArray(), - // extraData: _emptyKeyValueArray(), - // nftName: "Bitcoin", - // nftSymbol: "BTC" - // }) - // ); + namespace = INamespace( + lensFactory.deployNamespace({ + namespace: "bitcoin", + metadataURI: "satoshi://nakamoto", + owner: namespaceOwner, + admins: _emptyAddressArray(), + rules: _emptyRuleChangeArray(), + extraData: _emptyKeyValueArray(), + nftName: "Bitcoin", + nftSymbol: "BTC" + }) + ); } function testCreateAssignUnassignDelete() public { From 706a0aa57d61c625656dcd711934df85e95abad3 Mon Sep 17 00:00:00 2001 From: vicnaum Date: Fri, 10 Jan 2025 11:24:46 +0100 Subject: [PATCH 08/41] misc: Rule Based Feed and Group made to compile without IR --- .../core/primitives/feed/RuleBasedFeed.sol | 266 ++++++++++-------- .../core/primitives/group/RuleBasedGroup.sol | 169 ++++++----- 2 files changed, 235 insertions(+), 200 deletions(-) diff --git a/contracts/core/primitives/feed/RuleBasedFeed.sol b/contracts/core/primitives/feed/RuleBasedFeed.sol index 8d2ab2da..41ff7587 100644 --- a/contracts/core/primitives/feed/RuleBasedFeed.sol +++ b/contracts/core/primitives/feed/RuleBasedFeed.sol @@ -136,121 +136,132 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { // Internal function _encodeAndCallProcessCreatePostOnFeed( - address rule, - bytes32 configSalt, - uint256, /* rootPostId */ - uint256 postId, - CreatePostParams calldata postParams, - KeyValue[] calldata primitiveCustomParams, + Rule memory rule, + ProcessPostCreationParams memory processParams, KeyValue[] memory ruleCustomParams ) internal returns (bool, bytes memory) { - return rule.safecall( + return rule.ruleAddress.safecall( abi.encodeCall( - IFeedRule.processCreatePost, (configSalt, postId, postParams, primitiveCustomParams, ruleCustomParams) + IFeedRule.processCreatePost, + ( + rule.configSalt, + processParams.postId, + processParams.postParams, + processParams.primitiveCustomParams, + ruleCustomParams + ) ) ); } function _encodeAndCallProcessCreatePostOnRootPost( - address rule, - bytes32 configSalt, - uint256 rootPostId, - uint256 postId, - CreatePostParams calldata postParams, - KeyValue[] calldata primitiveCustomParams, + Rule memory rule, + ProcessPostCreationParams memory processParams, KeyValue[] memory ruleCustomParams ) internal returns (bool, bytes memory) { - return rule.safecall( + return rule.ruleAddress.safecall( abi.encodeCall( IPostRule.processCreatePost, - (configSalt, rootPostId, postId, postParams, primitiveCustomParams, ruleCustomParams) + ( + rule.configSalt, + processParams.rootPostId, + processParams.postId, + processParams.postParams, + processParams.primitiveCustomParams, + ruleCustomParams + ) ) ); } + struct ProcessPostCreationParams { + bytes4 ruleSelector; + uint256 rootPostId; + uint256 postId; + CreatePostParams postParams; + KeyValue[] primitiveCustomParams; + RuleProcessingParams[] rulesProcessingParams; + } + function _processPostCreation( - function(address,bytes32,uint256,uint256,CreatePostParams calldata,KeyValue[] calldata,KeyValue[] memory) internal returns (bool, bytes memory) + function(Rule memory,ProcessPostCreationParams memory,KeyValue[] memory) internal returns (bool, bytes memory) encodeAndCall, - bytes4 ruleSelector, - uint256 rootPostId, - uint256 postId, - CreatePostParams calldata postParams, - KeyValue[] calldata customParams, - RuleProcessingParams[] calldata rulesProcessingParams + ProcessPostCreationParams memory processParams ) internal { - RulesStorage storage _rulesStorage = rootPostId == 0 ? $feedRulesStorage() : $postRulesStorage(rootPostId); + RulesStorage storage _rulesStorage = + processParams.rootPostId == 0 ? $feedRulesStorage() : $postRulesStorage(processParams.rootPostId); // Check required rules (AND-combined rules) - for (uint256 i = 0; i < _rulesStorage.requiredRules[ruleSelector].length; i++) { - Rule memory rule = _rulesStorage.requiredRules[ruleSelector][i]; - for (uint256 j = 0; j < rulesProcessingParams.length; j++) { + for (uint256 i = 0; i < _rulesStorage.requiredRules[processParams.ruleSelector].length; i++) { + Rule memory rule = _rulesStorage.requiredRules[processParams.ruleSelector][i]; + for (uint256 j = 0; j < processParams.rulesProcessingParams.length; j++) { KeyValue[] memory ruleCustomParams = new KeyValue[](0); if ( - rulesProcessingParams[j].ruleAddress == rule.ruleAddress - && rulesProcessingParams[j].configSalt == rule.configSalt + processParams.rulesProcessingParams[j].ruleAddress == rule.ruleAddress + && processParams.rulesProcessingParams[j].configSalt == rule.configSalt ) { - ruleCustomParams = rulesProcessingParams[j].ruleParams; + ruleCustomParams = processParams.rulesProcessingParams[j].ruleParams; } - // (bool callNotReverted,) = encodeAndCall( - // rule.ruleAddress, rule.configSalt, rootPostId, postId, postParams, customParams, ruleCustomParams - // ); - // require(callNotReverted, Errors.RequiredRuleReverted()); + (bool callNotReverted,) = encodeAndCall(rule, processParams, ruleCustomParams); + require(callNotReverted, Errors.RequiredRuleReverted()); } } // Check any-of rules (OR-combined rules) - for (uint256 i = 0; i < _rulesStorage.anyOfRules[ruleSelector].length; i++) { - Rule memory rule = _rulesStorage.anyOfRules[ruleSelector][i]; - for (uint256 j = 0; j < rulesProcessingParams.length; j++) { + for (uint256 i = 0; i < _rulesStorage.anyOfRules[processParams.ruleSelector].length; i++) { + Rule memory rule = _rulesStorage.anyOfRules[processParams.ruleSelector][i]; + for (uint256 j = 0; j < processParams.rulesProcessingParams.length; j++) { KeyValue[] memory ruleCustomParams = new KeyValue[](0); if ( - rulesProcessingParams[j].ruleAddress == rule.ruleAddress - && rulesProcessingParams[j].configSalt == rule.configSalt + processParams.rulesProcessingParams[j].ruleAddress == rule.ruleAddress + && processParams.rulesProcessingParams[j].configSalt == rule.configSalt ) { - ruleCustomParams = rulesProcessingParams[j].ruleParams; + ruleCustomParams = processParams.rulesProcessingParams[j].ruleParams; + } + (bool callNotReverted,) = encodeAndCall(rule, processParams, ruleCustomParams); + if (callNotReverted) { + return; // If any of the OR-combined rules passed, it means they succeed and we can return } - // (bool callNotReverted,) = encodeAndCall( - // rule.ruleAddress, rule.configSalt, rootPostId, postId, postParams, customParams, ruleCustomParams - // ); - // if (callNotReverted) { - // return; // If any of the OR-combined rules passed, it means they succeed and we can return - // } } } // If there are any-of rules and it reached this point, it means all of them failed. - require(_rulesStorage.anyOfRules[ruleSelector].length == 0, Errors.AllAnyOfRulesReverted()); + require(_rulesStorage.anyOfRules[processParams.ruleSelector].length == 0, Errors.AllAnyOfRulesReverted()); } function _processPostCreationOnRootPost( uint256 rootPostId, uint256 postId, CreatePostParams calldata postParams, - KeyValue[] calldata customParams, + KeyValue[] calldata primitiveCustomParams, RuleProcessingParams[] calldata postRulesParams ) internal { _processPostCreation( _encodeAndCallProcessCreatePostOnRootPost, - IPostRule.processCreatePost.selector, - rootPostId, - postId, - postParams, - customParams, - postRulesParams + ProcessPostCreationParams({ + ruleSelector: IPostRule.processCreatePost.selector, + rootPostId: rootPostId, + postId: postId, + postParams: postParams, + primitiveCustomParams: primitiveCustomParams, + rulesProcessingParams: postRulesParams + }) ); } function _processPostCreationOnFeed( uint256 postId, CreatePostParams calldata postParams, - KeyValue[] calldata customParams, + KeyValue[] calldata primitiveCustomParams, RuleProcessingParams[] calldata feedRulesParams ) internal { _processPostCreation( _encodeAndCallProcessCreatePostOnFeed, - IFeedRule.processCreatePost.selector, - 0, - postId, - postParams, - customParams, - feedRulesParams + ProcessPostCreationParams({ + ruleSelector: IFeedRule.processCreatePost.selector, + rootPostId: 0, + postId: postId, + postParams: postParams, + primitiveCustomParams: primitiveCustomParams, + rulesProcessingParams: feedRulesParams + }) ); } @@ -258,119 +269,130 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { uint256 rootPostId, uint256 postId, EditPostParams calldata postParams, - KeyValue[] calldata customParams, + KeyValue[] calldata primitiveCustomParams, RuleProcessingParams[] calldata postRulesParams ) internal { _processPostEditing( _encodeAndCallProcessEditPostOnRootPost, - IPostRule.processEditPost.selector, - rootPostId, - postId, - postParams, - customParams, - postRulesParams + ProcessPostEditingParams({ + ruleSelector: IPostRule.processEditPost.selector, + rootPostId: rootPostId, + postId: postId, + postParams: postParams, + primitiveCustomParams: primitiveCustomParams, + rulesProcessingParams: postRulesParams + }) ); } function _processPostEditingOnFeed( uint256 postId, EditPostParams calldata postParams, - KeyValue[] calldata customParams, + KeyValue[] calldata primitiveCustomParams, RuleProcessingParams[] calldata feedRulesParams ) internal { _processPostEditing( _encodeAndCallProcessEditPostOnFeed, - IFeedRule.processEditPost.selector, - 0, - postId, - postParams, - customParams, - feedRulesParams + ProcessPostEditingParams({ + ruleSelector: IFeedRule.processEditPost.selector, + rootPostId: 0, + postId: postId, + postParams: postParams, + primitiveCustomParams: primitiveCustomParams, + rulesProcessingParams: feedRulesParams + }) ); } function _encodeAndCallProcessEditPostOnFeed( - address rule, - bytes32 configSalt, - uint256, /* rootPostId */ - uint256 postId, - EditPostParams calldata postParams, - KeyValue[] calldata primitiveCustomParams, + Rule memory rule, + ProcessPostEditingParams memory processParams, KeyValue[] memory ruleCustomParams ) internal returns (bool, bytes memory) { - return rule.safecall( + return rule.ruleAddress.safecall( abi.encodeCall( - IFeedRule.processEditPost, (configSalt, postId, postParams, primitiveCustomParams, ruleCustomParams) + IFeedRule.processEditPost, + ( + rule.configSalt, + processParams.postId, + processParams.postParams, + processParams.primitiveCustomParams, + ruleCustomParams + ) ) ); } function _encodeAndCallProcessEditPostOnRootPost( - address rule, - bytes32 configSalt, - uint256 rootPostId, - uint256 postId, - EditPostParams calldata postParams, - KeyValue[] calldata primitiveCustomParams, + Rule memory rule, + ProcessPostEditingParams memory processParams, KeyValue[] memory ruleCustomParams ) internal returns (bool, bytes memory) { - return rule.safecall( + return rule.ruleAddress.safecall( abi.encodeCall( IPostRule.processEditPost, - (configSalt, rootPostId, postId, postParams, primitiveCustomParams, ruleCustomParams) + ( + rule.configSalt, + processParams.rootPostId, + processParams.postId, + processParams.postParams, + processParams.primitiveCustomParams, + ruleCustomParams + ) ) ); } + struct ProcessPostEditingParams { + bytes4 ruleSelector; + uint256 rootPostId; + uint256 postId; + EditPostParams postParams; + KeyValue[] primitiveCustomParams; + RuleProcessingParams[] rulesProcessingParams; + } + function _processPostEditing( - function(address,bytes32,uint256,uint256,EditPostParams calldata,KeyValue[] calldata,KeyValue[] memory) internal returns (bool, bytes memory) + function(Rule memory,ProcessPostEditingParams memory,KeyValue[] memory) internal returns (bool,bytes memory) encodeAndCall, - bytes4 ruleSelector, - uint256 rootPostId, - uint256 postId, - EditPostParams calldata postParams, - KeyValue[] calldata customParams, - RuleProcessingParams[] calldata rulesProcessingParams + ProcessPostEditingParams memory processParams ) internal { - RulesStorage storage _rulesStorage = rootPostId == 0 ? $feedRulesStorage() : $postRulesStorage(rootPostId); + RulesStorage storage _rulesStorage = + processParams.rootPostId == 0 ? $feedRulesStorage() : $postRulesStorage(processParams.rootPostId); // Check required rules (AND-combined rules) - for (uint256 i = 0; i < _rulesStorage.requiredRules[ruleSelector].length; i++) { - Rule memory rule = _rulesStorage.requiredRules[ruleSelector][i]; - for (uint256 j = 0; j < rulesProcessingParams.length; j++) { + for (uint256 i = 0; i < _rulesStorage.requiredRules[processParams.ruleSelector].length; i++) { + Rule memory rule = _rulesStorage.requiredRules[processParams.ruleSelector][i]; + for (uint256 j = 0; j < processParams.rulesProcessingParams.length; j++) { KeyValue[] memory ruleCustomParams = new KeyValue[](0); if ( - rulesProcessingParams[j].ruleAddress == rule.ruleAddress - && rulesProcessingParams[j].configSalt == rule.configSalt + processParams.rulesProcessingParams[j].ruleAddress == rule.ruleAddress + && processParams.rulesProcessingParams[j].configSalt == rule.configSalt ) { - ruleCustomParams = rulesProcessingParams[j].ruleParams; + ruleCustomParams = processParams.rulesProcessingParams[j].ruleParams; } - // (bool callNotReverted,) = encodeAndCall( - // rule.ruleAddress, rule.configSalt, rootPostId, postId, postParams, customParams, ruleCustomParams - // ); - // require(callNotReverted, Errors.RequiredRuleReverted()); + (bool callNotReverted,) = encodeAndCall(rule, processParams, ruleCustomParams); + require(callNotReverted, Errors.RequiredRuleReverted()); } } // Check any-of rules (OR-combined rules) - for (uint256 i = 0; i < _rulesStorage.anyOfRules[ruleSelector].length; i++) { - Rule memory rule = _rulesStorage.anyOfRules[ruleSelector][i]; - for (uint256 j = 0; j < rulesProcessingParams.length; j++) { + for (uint256 i = 0; i < _rulesStorage.anyOfRules[processParams.ruleSelector].length; i++) { + Rule memory rule = _rulesStorage.anyOfRules[processParams.ruleSelector][i]; + for (uint256 j = 0; j < processParams.rulesProcessingParams.length; j++) { KeyValue[] memory ruleCustomParams = new KeyValue[](0); if ( - rulesProcessingParams[j].ruleAddress == rule.ruleAddress - && rulesProcessingParams[j].configSalt == rule.configSalt + processParams.rulesProcessingParams[j].ruleAddress == rule.ruleAddress + && processParams.rulesProcessingParams[j].configSalt == rule.configSalt ) { - ruleCustomParams = rulesProcessingParams[j].ruleParams; + ruleCustomParams = processParams.rulesProcessingParams[j].ruleParams; + } + (bool callNotReverted,) = encodeAndCall(rule, processParams, ruleCustomParams); + if (callNotReverted) { + return; // If any of the OR-combined rules passed, it means they succeed and we can return } - // (bool callNotReverted,) = encodeAndCall( - // rule.ruleAddress, rule.configSalt, rootPostId, postId, postParams, customParams, ruleCustomParams - // ); - // if (callNotReverted) { - // return; // If any of the OR-combined rules passed, it means they succeed and we can return - // } } } // If there are any-of rules and it reached this point, it means all of them failed. - require(_rulesStorage.anyOfRules[ruleSelector].length == 0, Errors.AllAnyOfRulesReverted()); + require(_rulesStorage.anyOfRules[processParams.ruleSelector].length == 0, Errors.AllAnyOfRulesReverted()); } function _processPostRemoval( diff --git a/contracts/core/primitives/group/RuleBasedGroup.sol b/contracts/core/primitives/group/RuleBasedGroup.sol index 480aee7d..95cb3e6b 100644 --- a/contracts/core/primitives/group/RuleBasedGroup.sol +++ b/contracts/core/primitives/group/RuleBasedGroup.sol @@ -100,17 +100,20 @@ abstract contract RuleBasedGroup is IGroup, RuleBasedPrimitive { //////////////////////////// PROCESSING FUNCTIONS //////////////////////////// function _encodeAndCallProcessMemberRemoval( - address rule, - bytes32 configSalt, - address originalMsgSender, - address account, - KeyValue[] calldata primitiveCustomParams, + Rule memory rule, + ProcessParams memory processParams, KeyValue[] memory ruleCustomParams ) internal returns (bool, bytes memory) { - return rule.safecall( + return rule.ruleAddress.safecall( abi.encodeCall( IGroupRule.processRemoval, - (configSalt, originalMsgSender, account, primitiveCustomParams, ruleCustomParams) + ( + rule.configSalt, + processParams.originalMsgSender, + processParams.account, + processParams.primitiveCustomParams, + ruleCustomParams + ) ) ); } @@ -123,26 +126,31 @@ abstract contract RuleBasedGroup is IGroup, RuleBasedPrimitive { ) internal { _processGroupRule( _encodeAndCallProcessMemberRemoval, - IGroupRule.processRemoval.selector, - originalMsgSender, - account, - primitiveCustomParams, - ruleProcessingParams + ProcessParams({ + ruleSelector: IGroupRule.processRemoval.selector, + originalMsgSender: originalMsgSender, + account: account, + primitiveCustomParams: primitiveCustomParams, + rulesProcessingParams: ruleProcessingParams + }) ); } function _encodeAndCallProcessMemberAddition( - address rule, - bytes32 configSalt, - address originalMsgSender, - address account, - KeyValue[] calldata primitiveCustomParams, + Rule memory rule, + ProcessParams memory processParams, KeyValue[] memory ruleCustomParams ) internal returns (bool, bytes memory) { - return rule.safecall( + return rule.ruleAddress.safecall( abi.encodeCall( IGroupRule.processAddition, - (configSalt, originalMsgSender, account, primitiveCustomParams, ruleCustomParams) + ( + rule.configSalt, + processParams.originalMsgSender, + processParams.account, + processParams.primitiveCustomParams, + ruleCustomParams + ) ) ); } @@ -155,24 +163,26 @@ abstract contract RuleBasedGroup is IGroup, RuleBasedPrimitive { ) internal { _processGroupRule( _encodeAndCallProcessMemberAddition, - IGroupRule.processAddition.selector, - originalMsgSender, - account, - primitiveCustomParams, - ruleProcessingParams + ProcessParams({ + ruleSelector: IGroupRule.processAddition.selector, + originalMsgSender: originalMsgSender, + account: account, + primitiveCustomParams: primitiveCustomParams, + rulesProcessingParams: ruleProcessingParams + }) ); } function _encodeAndCallProcessMemberJoining( - address rule, - bytes32 configSalt, - address, /* originalMsgSender */ - address account, - KeyValue[] calldata primitiveCustomParams, + Rule memory rule, + ProcessParams memory processParams, KeyValue[] memory ruleCustomParams ) internal returns (bool, bytes memory) { - return rule.safecall( - abi.encodeCall(IGroupRule.processJoining, (configSalt, account, primitiveCustomParams, ruleCustomParams)) + return rule.ruleAddress.safecall( + abi.encodeCall( + IGroupRule.processJoining, + (rule.configSalt, processParams.account, processParams.primitiveCustomParams, ruleCustomParams) + ) ); } @@ -184,24 +194,26 @@ abstract contract RuleBasedGroup is IGroup, RuleBasedPrimitive { ) internal { _processGroupRule( _encodeAndCallProcessMemberJoining, - IGroupRule.processJoining.selector, - originalMsgSender, - account, - primitiveCustomParams, - ruleProcessingParams + ProcessParams({ + ruleSelector: IGroupRule.processJoining.selector, + originalMsgSender: originalMsgSender, + account: account, + primitiveCustomParams: primitiveCustomParams, + rulesProcessingParams: ruleProcessingParams + }) ); } function _encodeAndCallProcessMemberLeaving( - address rule, - bytes32 configSalt, - address, /* originalMsgSender */ - address account, - KeyValue[] calldata primitiveCustomParams, + Rule memory rule, + ProcessParams memory processParams, KeyValue[] memory ruleCustomParams ) internal returns (bool, bytes memory) { - return rule.safecall( - abi.encodeCall(IGroupRule.processLeaving, (configSalt, account, primitiveCustomParams, ruleCustomParams)) + return rule.ruleAddress.safecall( + abi.encodeCall( + IGroupRule.processLeaving, + (rule.configSalt, processParams.account, processParams.primitiveCustomParams, ruleCustomParams) + ) ); } @@ -213,60 +225,61 @@ abstract contract RuleBasedGroup is IGroup, RuleBasedPrimitive { ) internal { _processGroupRule( _encodeAndCallProcessMemberLeaving, - IGroupRule.processLeaving.selector, - originalMsgSender, - account, - primitiveCustomParams, - ruleProcessingParams + ProcessParams({ + ruleSelector: IGroupRule.processLeaving.selector, + originalMsgSender: originalMsgSender, + account: account, + primitiveCustomParams: primitiveCustomParams, + rulesProcessingParams: ruleProcessingParams + }) ); } + struct ProcessParams { + bytes4 ruleSelector; + address originalMsgSender; + address account; + KeyValue[] primitiveCustomParams; + RuleProcessingParams[] rulesProcessingParams; + } + function _processGroupRule( - function(address,bytes32,address,address,KeyValue[] calldata,KeyValue[] memory) internal returns (bool,bytes memory) - encodeAndCall, - bytes4 ruleSelector, - address originalMsgSender, - address account, - KeyValue[] calldata primitiveCustomParams, - RuleProcessingParams[] calldata rulesProcessingParams + function(Rule memory,ProcessParams memory,KeyValue[] memory) internal returns (bool,bytes memory) encodeAndCall, + ProcessParams memory processParams ) private { // Check required rules (AND-combined rules) - for (uint256 i = 0; i < $groupRulesStorage().requiredRules[ruleSelector].length; i++) { - Rule memory rule = $groupRulesStorage().requiredRules[ruleSelector][i]; - for (uint256 j = 0; j < rulesProcessingParams.length; j++) { + for (uint256 i = 0; i < $groupRulesStorage().requiredRules[processParams.ruleSelector].length; i++) { + Rule memory rule = $groupRulesStorage().requiredRules[processParams.ruleSelector][i]; + for (uint256 j = 0; j < processParams.rulesProcessingParams.length; j++) { KeyValue[] memory ruleParams = new KeyValue[](0); if ( - rulesProcessingParams[j].ruleAddress == rule.ruleAddress - && rulesProcessingParams[j].configSalt == rule.configSalt + processParams.rulesProcessingParams[j].ruleAddress == rule.ruleAddress + && processParams.rulesProcessingParams[j].configSalt == rule.configSalt ) { - ruleParams = rulesProcessingParams[j].ruleParams; + ruleParams = processParams.rulesProcessingParams[j].ruleParams; } - // (bool callNotReverted,) = encodeAndCall( - // rule.ruleAddress, rule.configSalt, originalMsgSender, account, primitiveCustomParams, ruleParams - // ); - // require(callNotReverted, Errors.RequiredRuleReverted()); + (bool callNotReverted,) = encodeAndCall(rule, processParams, ruleParams); + require(callNotReverted, Errors.RequiredRuleReverted()); } } // Check any-of rules (OR-combined rules) - for (uint256 i = 0; i < $groupRulesStorage().anyOfRules[ruleSelector].length; i++) { - Rule memory rule = $groupRulesStorage().anyOfRules[ruleSelector][i]; - for (uint256 j = 0; j < rulesProcessingParams.length; j++) { + for (uint256 i = 0; i < $groupRulesStorage().anyOfRules[processParams.ruleSelector].length; i++) { + Rule memory rule = $groupRulesStorage().anyOfRules[processParams.ruleSelector][i]; + for (uint256 j = 0; j < processParams.rulesProcessingParams.length; j++) { KeyValue[] memory ruleParams = new KeyValue[](0); if ( - rulesProcessingParams[j].ruleAddress == rule.ruleAddress - && rulesProcessingParams[j].configSalt == rule.configSalt + processParams.rulesProcessingParams[j].ruleAddress == rule.ruleAddress + && processParams.rulesProcessingParams[j].configSalt == rule.configSalt ) { - ruleParams = rulesProcessingParams[j].ruleParams; + ruleParams = processParams.rulesProcessingParams[j].ruleParams; + } + (bool callNotReverted,) = encodeAndCall(rule, processParams, ruleParams); + if (callNotReverted) { + return; // If any of the OR-combined rules passed, it means they succeed and we can return } - // (bool callNotReverted,) = encodeAndCall( - // rule.ruleAddress, rule.configSalt, originalMsgSender, account, primitiveCustomParams, ruleParams - // ); - // if (callNotReverted) { - // return; // If any of the OR-combined rules passed, it means they succeed and we can return - // } } } // If there are any-of rules and it reached this point, it means all of them failed. - require($groupRulesStorage().anyOfRules[ruleSelector].length == 0, Errors.AllAnyOfRulesReverted()); + require($groupRulesStorage().anyOfRules[processParams.ruleSelector].length == 0, Errors.AllAnyOfRulesReverted()); } } From 0ba5dd181c2ef0e595e7e7f89cbaba4fe8c146bb Mon Sep 17 00:00:00 2001 From: vicnaum Date: Fri, 10 Jan 2025 11:36:02 +0100 Subject: [PATCH 09/41] misc: RuleBasePrimitive made to compile without IR --- contracts/core/base/RuleBasedPrimitive.sol | 80 +++++++++---------- contracts/core/libraries/RulesLib.sol | 28 ++++--- contracts/core/primitives/feed/Feed.sol | 4 +- .../core/primitives/feed/RuleBasedFeed.sol | 4 +- contracts/core/primitives/graph/Graph.sol | 4 +- .../core/primitives/graph/RuleBasedGraph.sol | 4 +- contracts/core/primitives/group/Group.sol | 2 +- .../core/primitives/group/RuleBasedGroup.sol | 4 +- .../core/primitives/namespace/Namespace.sol | 2 +- .../namespace/RuleBasedNamespace.sol | 4 +- 10 files changed, 70 insertions(+), 66 deletions(-) diff --git a/contracts/core/base/RuleBasedPrimitive.sol b/contracts/core/base/RuleBasedPrimitive.sol index 7f92b03c..e1acb778 100644 --- a/contracts/core/base/RuleBasedPrimitive.sol +++ b/contracts/core/base/RuleBasedPrimitive.sol @@ -18,7 +18,7 @@ abstract contract RuleBasedPrimitive { using RulesLib for RulesStorage; using CallLib for address; - function _changePrimitiveRules(RulesStorage storage rulesStorage, RuleChange[] calldata ruleChanges) + function _changePrimitiveRules(RulesStorage storage rulesStorage, RuleChange[] memory ruleChanges) internal virtual { @@ -36,8 +36,8 @@ abstract contract RuleBasedPrimitive { function _changeEntityRules( RulesStorage storage rulesStorage, uint256 entityId, - RuleChange[] calldata ruleChanges, - RuleProcessingParams[] calldata ruleChangesProcessingParams + RuleChange[] memory ruleChanges, + RuleProcessingParams[] memory ruleChangesProcessingParams ) internal virtual { _changeRules( rulesStorage, @@ -50,7 +50,7 @@ abstract contract RuleBasedPrimitive { ); } - function _encodeConfigureCall(uint256 entityId, bytes32 configSalt, KeyValue[] calldata ruleParams) + function _encodeConfigureCall(uint256 entityId, bytes32 configSalt, KeyValue[] memory ruleParams) internal pure returns (bytes memory) @@ -67,7 +67,7 @@ abstract contract RuleBasedPrimitive { uint256 entityId, address ruleAddress, bytes32 configSalt, - KeyValue[] calldata ruleParams + KeyValue[] memory ruleParams ) internal { if (entityId == 0) { _emitPrimitiveRuleConfiguredEvent(wasAlreadyConfigured, ruleAddress, configSalt, ruleParams); @@ -93,7 +93,7 @@ abstract contract RuleBasedPrimitive { // Primitive functions: - function _encodePrimitiveConfigureCall(bytes32 configSalt, KeyValue[] calldata ruleParams) + function _encodePrimitiveConfigureCall(bytes32 configSalt, KeyValue[] memory ruleParams) internal pure virtual @@ -103,7 +103,7 @@ abstract contract RuleBasedPrimitive { bool wasAlreadyConfigured, address ruleAddress, bytes32 configSalt, - KeyValue[] calldata ruleParams + KeyValue[] memory ruleParams ) internal virtual; function _emitPrimitiveRuleSelectorEvent( @@ -116,7 +116,7 @@ abstract contract RuleBasedPrimitive { // Entity functions: - function _encodeEntityConfigureCall(uint256 entityId, bytes32 configSalt, KeyValue[] calldata ruleParams) + function _encodeEntityConfigureCall(uint256 entityId, bytes32 configSalt, KeyValue[] memory ruleParams) internal pure virtual @@ -128,7 +128,7 @@ abstract contract RuleBasedPrimitive { uint256 entityId, address ruleAddress, bytes32 configSalt, - KeyValue[] calldata ruleParams + KeyValue[] memory ruleParams ) internal virtual {} function _emitEntityRuleSelectorEvent( @@ -145,40 +145,27 @@ abstract contract RuleBasedPrimitive { function _changeRules( RulesStorage storage rulesStorage, uint256 entityId, - RuleChange[] calldata ruleChanges, + RuleChange[] memory ruleChanges, RuleProcessingParams[] memory ruleChangesProcessingParams, - function(uint256,bytes32,KeyValue[] calldata) internal returns (bytes memory) fn_encodeConfigureCall, - function(bool,uint256,address,bytes32,KeyValue[] calldata) internal fn_emitConfiguredEvent, + function(uint256,bytes32,KeyValue[] memory) internal returns (bytes memory) fn_encodeConfigureCall, + function(bool,uint256,address,bytes32,KeyValue[] memory) internal fn_emitConfiguredEvent, function(bool,uint256,address,bytes32,bool,bytes4) internal fn_emitSelectorEvent ) private { _beforeChangeRules(entityId, ruleChanges); for (uint256 i = 0; i < ruleChanges.length; i++) { RuleChange memory ruleChange = ruleChanges[i]; if (ruleChange.configurationChanges.configure) { - ruleChange.configSalt = _configureRule( - rulesStorage, - ruleChanges[i].ruleAddress, - ruleChanges[i].configSalt, - entityId, - ruleChanges[i].configurationChanges.ruleParams, - fn_encodeConfigureCall, - fn_emitConfiguredEvent - ); + ruleChange.configSalt = + _configureRule(rulesStorage, ruleChange, entityId, fn_encodeConfigureCall, fn_emitConfiguredEvent); } for (uint256 j = 0; j < ruleChange.selectorChanges.length; j++) { _validateIsSupportedRuleSelector( ruleChange.selectorChanges[j].ruleSelector, entityId == 0 ? _supportedPrimitiveRuleSelectors() : _supportedEntityRuleSelectors() ); - // rulesStorage._changeRulesSelectors( - // ruleChanges[i].ruleAddress, - // ruleChange.configSalt, - // entityId, - // ruleChanges[i].selectorChanges[j].ruleSelector, - // ruleChanges[i].selectorChanges[j].isRequired, - // ruleChanges[i].selectorChanges[j].enabled, - // fn_emitSelectorEvent - // ); + rulesStorage._changeRulesSelectors( + ruleChange, entityId, ruleChange.selectorChanges[j], fn_emitSelectorEvent + ); } } if (entityId == 0) { @@ -207,7 +194,7 @@ abstract contract RuleBasedPrimitive { revert Errors.UnsupportedSelector(); } - function _beforeChangeRules(uint256 entityId, RuleChange[] calldata ruleChanges) internal virtual { + function _beforeChangeRules(uint256 entityId, RuleChange[] memory ruleChanges) internal virtual { if (entityId == 0) { _beforeChangePrimitiveRules(ruleChanges); } else { @@ -217,7 +204,7 @@ abstract contract RuleBasedPrimitive { function _processEntityRulesChanges( uint256 entityId, - RuleChange[] calldata ruleChanges, + RuleChange[] memory ruleChanges, RuleProcessingParams[] memory ruleChangesProcessingParams ) internal virtual {} @@ -234,23 +221,30 @@ abstract contract RuleBasedPrimitive { } } - function _beforeChangePrimitiveRules(RuleChange[] calldata ruleChanges) internal virtual {} + function _beforeChangePrimitiveRules(RuleChange[] memory ruleChanges) internal virtual {} - function _beforeChangeEntityRules(uint256 entityId, RuleChange[] calldata ruleChanges) internal virtual {} + function _beforeChangeEntityRules(uint256 entityId, RuleChange[] memory ruleChanges) internal virtual {} function _configureRule( RulesStorage storage rulesStorage, - address ruleAddress, - bytes32 providedConfigSalt, + RuleChange memory ruleChange, uint256 entityId, - KeyValue[] calldata ruleParams, - function(uint256,bytes32,KeyValue[] calldata) internal returns (bytes memory) fn_encodeConfigureCall, - function(bool,uint256,address,bytes32,KeyValue[] calldata) internal fn_emitEvent + function(uint256,bytes32,KeyValue[] memory) internal returns (bytes memory) fn_encodeConfigureCall, + function(bool,uint256,address,bytes32,KeyValue[] memory) internal fn_emitEvent ) internal returns (bytes32) { - bytes32 configSalt = rulesStorage.generateOrValidateConfigSalt(ruleAddress, providedConfigSalt); - bool wasAlreadyConfigured = - rulesStorage.configureRule(ruleAddress, configSalt, fn_encodeConfigureCall(entityId, configSalt, ruleParams)); - fn_emitEvent(wasAlreadyConfigured, entityId, ruleAddress, configSalt, ruleParams); + bytes32 configSalt = rulesStorage.generateOrValidateConfigSalt(ruleChange.ruleAddress, ruleChange.configSalt); + bool wasAlreadyConfigured = rulesStorage.configureRule( + ruleChange.ruleAddress, + configSalt, + fn_encodeConfigureCall(entityId, configSalt, ruleChange.configurationChanges.ruleParams) + ); + fn_emitEvent( + wasAlreadyConfigured, + entityId, + ruleChange.ruleAddress, + configSalt, + ruleChange.configurationChanges.ruleParams + ); return configSalt; } } diff --git a/contracts/core/libraries/RulesLib.sol b/contracts/core/libraries/RulesLib.sol index 82d16d94..15547514 100644 --- a/contracts/core/libraries/RulesLib.sol +++ b/contracts/core/libraries/RulesLib.sol @@ -2,7 +2,7 @@ // Copyright (C) 2024 Lens Labs. All Rights Reserved. pragma solidity ^0.8.26; -import {Rule} from "contracts/core/types/Types.sol"; +import {Rule, RuleChange, RuleSelectorChange} from "contracts/core/types/Types.sol"; import {CallLib} from "contracts/core/libraries/CallLib.sol"; import {Errors} from "contracts/core/types/Errors.sol"; @@ -89,18 +89,28 @@ library RulesLib { function _changeRulesSelectors( RulesStorage storage rulesStorage, - address ruleAddress, - bytes32 configSalt, + RuleChange memory ruleChange, uint256 entityId, - bytes4 ruleSelector, - bool isRequired, - bool enabled, + RuleSelectorChange memory ruleSelectorChange, function(bool,uint256,address,bytes32,bool,bytes4) internal fn_emitEvent ) internal { function(RulesStorage storage, bool, address, bytes32, bytes4) internal fn_changeRuleSelector = - enabled ? RulesLib.enableRuleSelector : RulesLib.disableRuleSelector; - fn_changeRuleSelector(rulesStorage, isRequired, ruleAddress, configSalt, ruleSelector); - fn_emitEvent(enabled, entityId, ruleAddress, configSalt, isRequired, ruleSelector); + ruleSelectorChange.enabled ? RulesLib.enableRuleSelector : RulesLib.disableRuleSelector; + fn_changeRuleSelector( + rulesStorage, + ruleSelectorChange.isRequired, + ruleChange.ruleAddress, + ruleChange.configSalt, + ruleSelectorChange.ruleSelector + ); + fn_emitEvent( + ruleSelectorChange.enabled, + entityId, + ruleChange.ruleAddress, + ruleChange.configSalt, + ruleSelectorChange.isRequired, + ruleSelectorChange.ruleSelector + ); } // Private diff --git a/contracts/core/primitives/feed/Feed.sol b/contracts/core/primitives/feed/Feed.sol index b067c001..e7f5b5b8 100644 --- a/contracts/core/primitives/feed/Feed.sol +++ b/contracts/core/primitives/feed/Feed.sol @@ -69,11 +69,11 @@ contract Feed is _requireAccess(msg.sender, PID__SET_METADATA); } - function _beforeChangePrimitiveRules(RuleChange[] calldata /* ruleChanges */ ) internal virtual override { + function _beforeChangePrimitiveRules(RuleChange[] memory /* ruleChanges */ ) internal virtual override { _requireAccess(msg.sender, PID__CHANGE_RULES); } - function _beforeChangeEntityRules(uint256 entityId, RuleChange[] calldata /* ruleChanges */ ) + function _beforeChangeEntityRules(uint256 entityId, RuleChange[] memory /* ruleChanges */ ) internal virtual override diff --git a/contracts/core/primitives/feed/RuleBasedFeed.sol b/contracts/core/primitives/feed/RuleBasedFeed.sol index 41ff7587..547b9b5c 100644 --- a/contracts/core/primitives/feed/RuleBasedFeed.sol +++ b/contracts/core/primitives/feed/RuleBasedFeed.sol @@ -68,7 +68,7 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { return selectors; } - function _encodePrimitiveConfigureCall(bytes32 configSalt, KeyValue[] calldata ruleParams) + function _encodePrimitiveConfigureCall(bytes32 configSalt, KeyValue[] memory ruleParams) internal pure override @@ -81,7 +81,7 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { bool wasAlreadyConfigured, address ruleAddress, bytes32 configSalt, - KeyValue[] calldata ruleParams + KeyValue[] memory ruleParams ) internal override { if (wasAlreadyConfigured) { emit IFeed.Lens_Feed_RuleReconfigured(ruleAddress, configSalt, ruleParams); diff --git a/contracts/core/primitives/graph/Graph.sol b/contracts/core/primitives/graph/Graph.sol index ab16d57f..4ed4b3b2 100644 --- a/contracts/core/primitives/graph/Graph.sol +++ b/contracts/core/primitives/graph/Graph.sol @@ -65,11 +65,11 @@ contract Graph is _requireAccess(msg.sender, PID__SET_METADATA); } - function _beforeChangePrimitiveRules(RuleChange[] calldata /* ruleChanges */ ) internal virtual override { + function _beforeChangePrimitiveRules(RuleChange[] memory /* ruleChanges */ ) internal virtual override { _requireAccess(msg.sender, PID__CHANGE_RULES); } - function _beforeChangeEntityRules(uint256 entityId, RuleChange[] calldata /* ruleChanges */ ) + function _beforeChangeEntityRules(uint256 entityId, RuleChange[] memory /* ruleChanges */ ) internal virtual override diff --git a/contracts/core/primitives/graph/RuleBasedGraph.sol b/contracts/core/primitives/graph/RuleBasedGraph.sol index ea02f760..418877d1 100644 --- a/contracts/core/primitives/graph/RuleBasedGraph.sol +++ b/contracts/core/primitives/graph/RuleBasedGraph.sol @@ -67,7 +67,7 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive { return selectors; } - function _encodePrimitiveConfigureCall(bytes32 configSalt, KeyValue[] calldata ruleParams) + function _encodePrimitiveConfigureCall(bytes32 configSalt, KeyValue[] memory ruleParams) internal pure override @@ -80,7 +80,7 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive { bool wasAlreadyConfigured, address ruleAddress, bytes32 configSalt, - KeyValue[] calldata ruleParams + KeyValue[] memory ruleParams ) internal override { if (wasAlreadyConfigured) { emit IGraph.Lens_Graph_RuleReconfigured(ruleAddress, configSalt, ruleParams); diff --git a/contracts/core/primitives/group/Group.sol b/contracts/core/primitives/group/Group.sol index c9f79dd5..77d55c7c 100644 --- a/contracts/core/primitives/group/Group.sol +++ b/contracts/core/primitives/group/Group.sol @@ -71,7 +71,7 @@ contract Group is _requireAccess(msg.sender, PID__SET_METADATA); } - function _beforeChangePrimitiveRules(RuleChange[] calldata /* ruleChanges */ ) internal virtual override { + function _beforeChangePrimitiveRules(RuleChange[] memory /* ruleChanges */ ) internal virtual override { _requireAccess(msg.sender, PID__CHANGE_RULES); } diff --git a/contracts/core/primitives/group/RuleBasedGroup.sol b/contracts/core/primitives/group/RuleBasedGroup.sol index 95cb3e6b..ce7edf0c 100644 --- a/contracts/core/primitives/group/RuleBasedGroup.sol +++ b/contracts/core/primitives/group/RuleBasedGroup.sol @@ -46,7 +46,7 @@ abstract contract RuleBasedGroup is IGroup, RuleBasedPrimitive { return selectors; } - function _encodePrimitiveConfigureCall(bytes32 configSalt, KeyValue[] calldata ruleParams) + function _encodePrimitiveConfigureCall(bytes32 configSalt, KeyValue[] memory ruleParams) internal pure override @@ -59,7 +59,7 @@ abstract contract RuleBasedGroup is IGroup, RuleBasedPrimitive { bool wasAlreadyConfigured, address ruleAddress, bytes32 configSalt, - KeyValue[] calldata ruleParams + KeyValue[] memory ruleParams ) internal override { if (wasAlreadyConfigured) { emit IGroup.Lens_Group_RuleReconfigured(ruleAddress, configSalt, ruleParams); diff --git a/contracts/core/primitives/namespace/Namespace.sol b/contracts/core/primitives/namespace/Namespace.sol index 67ce98df..865e0e88 100644 --- a/contracts/core/primitives/namespace/Namespace.sol +++ b/contracts/core/primitives/namespace/Namespace.sol @@ -89,7 +89,7 @@ contract Namespace is _requireAccess(msg.sender, PID__SET_TOKEN_URI_PROVIDER); } - function _beforeChangePrimitiveRules(RuleChange[] calldata /* ruleChanges */ ) internal virtual override { + function _beforeChangePrimitiveRules(RuleChange[] memory /* ruleChanges */ ) internal virtual override { _requireAccess(msg.sender, PID__CHANGE_RULES); } // Permissionless functions diff --git a/contracts/core/primitives/namespace/RuleBasedNamespace.sol b/contracts/core/primitives/namespace/RuleBasedNamespace.sol index 9501a261..b1356b89 100644 --- a/contracts/core/primitives/namespace/RuleBasedNamespace.sol +++ b/contracts/core/primitives/namespace/RuleBasedNamespace.sol @@ -46,7 +46,7 @@ abstract contract RuleBasedNamespace is INamespace, RuleBasedPrimitive { return selectors; } - function _encodePrimitiveConfigureCall(bytes32 configSalt, KeyValue[] calldata ruleParams) + function _encodePrimitiveConfigureCall(bytes32 configSalt, KeyValue[] memory ruleParams) internal pure override @@ -59,7 +59,7 @@ abstract contract RuleBasedNamespace is INamespace, RuleBasedPrimitive { bool wasAlreadyConfigured, address ruleAddress, bytes32 configSalt, - KeyValue[] calldata ruleParams + KeyValue[] memory ruleParams ) internal override { if (wasAlreadyConfigured) { emit INamespace.Lens_Namespace_RuleReconfigured(ruleAddress, configSalt, ruleParams); From c5a740a8f000a032e2d7d660640b86d691a64b12 Mon Sep 17 00:00:00 2001 From: vicnaum Date: Fri, 10 Jan 2025 11:53:23 +0100 Subject: [PATCH 10/41] misc: Feed made to compile without IR --- contracts/core/base/SourceStampBased.sol | 6 +- contracts/core/primitives/feed/Feed.sol | 84 +++++++++---------- contracts/core/primitives/feed/FeedCore.sol | 2 +- .../core/primitives/feed/RuleBasedFeed.sol | 28 +++---- 4 files changed, 60 insertions(+), 60 deletions(-) diff --git a/contracts/core/base/SourceStampBased.sol b/contracts/core/base/SourceStampBased.sol index bd1b3069..72d5a2d4 100644 --- a/contracts/core/base/SourceStampBased.sol +++ b/contracts/core/base/SourceStampBased.sol @@ -16,7 +16,7 @@ abstract contract SourceStampBased is ExtraStorageBased { // TODO: We might consider moving source storing out of this contract (see Post created VS lastUpdated source) function _processSourceStamp( uint256 entityId, - KeyValue[] calldata customParams, + KeyValue[] memory customParams, bool storeSource, bool lastUpdatedSourceType ) internal returns (address) { @@ -40,14 +40,14 @@ abstract contract SourceStampBased is ExtraStorageBased { return address(0); } - function _processSourceStamp(uint256 entityId, KeyValue[] calldata customParams, bool storeSource) + function _processSourceStamp(uint256 entityId, KeyValue[] memory customParams, bool storeSource) internal returns (address) { return _processSourceStamp(entityId, customParams, storeSource, false); } - function _processSourceStamp(uint256 entityId, KeyValue[] calldata customParams) internal returns (address) { + function _processSourceStamp(uint256 entityId, KeyValue[] memory customParams) internal returns (address) { return _processSourceStamp(entityId, customParams, true, false); } diff --git a/contracts/core/primitives/feed/Feed.sol b/contracts/core/primitives/feed/Feed.sol index e7f5b5b8..8df76e91 100644 --- a/contracts/core/primitives/feed/Feed.sol +++ b/contracts/core/primitives/feed/Feed.sol @@ -84,11 +84,11 @@ contract Feed is // Public user functions function createPost( - CreatePostParams calldata postParams, - KeyValue[] calldata customParams, - RuleProcessingParams[] calldata feedRulesParams, - RuleProcessingParams[] calldata rootPostRulesParams, - RuleProcessingParams[] calldata quotedPostRulesParams + CreatePostParams memory postParams, + KeyValue[] memory customParams, + RuleProcessingParams[] memory feedRulesParams, + RuleProcessingParams[] memory rootPostRulesParams, + RuleProcessingParams[] memory quotedPostRulesParams ) external virtual override returns (uint256) { require(msg.sender == postParams.author, Errors.InvalidMsgSender()); (uint256 postId, uint256 authorPostSequentialId, uint256 rootPostId) = Core._createPost(postParams); @@ -98,46 +98,46 @@ contract Feed is // Process rules of the Quote (if quoting) if (postParams.quotedPostId != 0) { // TODO: Maybe quotes shouldn't be limited by rules... Just a brave thought. Like quotations in real life. - // uint256 rootOfQuotedPost = Core.$storage().posts[postParams.quotedPostId].rootPostId; - // if (rootOfQuotedPost != rootPostId) { - // _processPostCreationOnRootPost(rootOfQuotedPost, postId, postParams, customParams, quotedPostRulesParams); - // } + uint256 rootOfQuotedPost = Core.$storage().posts[postParams.quotedPostId].rootPostId; + if (rootOfQuotedPost != rootPostId) { + _processPostCreationOnRootPost(rootOfQuotedPost, postId, postParams, customParams, quotedPostRulesParams); + } } if (postId != rootPostId) { require(postParams.ruleChanges.length == 0, Errors.CannotHaveRules()); // This covers the Reply or Repost cases - // _processPostCreationOnRootPost(rootPostId, postId, postParams, customParams, rootPostRulesParams); + _processPostCreationOnRootPost(rootPostId, postId, postParams, customParams, rootPostRulesParams); } else { _addPostRulesAtCreation(postId, postParams, feedRulesParams); } - // emit Lens_Feed_PostCreated( - // postId, - // postParams.author, - // authorPostSequentialId, - // rootPostId, - // postParams, - // customParams, - // feedRulesParams, - // rootPostRulesParams, - // quotedPostRulesParams, - // source - // ); - // for (uint256 i = 0; i < postParams.extraData.length; i++) { - // _setEntityExtraData(postId, postParams.extraData[i]); - // emit Lens_Feed_Post_ExtraDataAdded( - // postId, postParams.extraData[i].key, postParams.extraData[i].value, postParams.extraData[i].value - // ); - // } + emit Lens_Feed_PostCreated( + postId, + postParams.author, + authorPostSequentialId, + rootPostId, + postParams, + customParams, + feedRulesParams, + rootPostRulesParams, + quotedPostRulesParams, + source + ); + for (uint256 i = 0; i < postParams.extraData.length; i++) { + _setEntityExtraData(postId, postParams.extraData[i]); + emit Lens_Feed_Post_ExtraDataAdded( + postId, postParams.extraData[i].key, postParams.extraData[i].value, postParams.extraData[i].value + ); + } return postId; } function editPost( uint256 postId, - EditPostParams calldata postParams, - KeyValue[] calldata customParams, - RuleProcessingParams[] calldata feedRulesParams, - RuleProcessingParams[] calldata rootPostRulesParams, - RuleProcessingParams[] calldata quotedPostRulesParams + EditPostParams memory postParams, + KeyValue[] memory customParams, + RuleProcessingParams[] memory feedRulesParams, + RuleProcessingParams[] memory rootPostRulesParams, + RuleProcessingParams[] memory quotedPostRulesParams ) external virtual override { address author = Core.$storage().posts[postId].author; // TODO: We can have this for moderators: @@ -165,18 +165,18 @@ contract Feed is storeSource: true, lastUpdatedSourceType: true }); - // emit Lens_Feed_PostEdited( - // postId, author, postParams, customParams, feedRulesParams, rootPostRulesParams, quotedPostRulesParams, source - // ); + emit Lens_Feed_PostEdited( + postId, author, postParams, customParams, feedRulesParams, rootPostRulesParams, quotedPostRulesParams, source + ); for (uint256 i = 0; i < postParams.extraData.length; i++) { if (wereExtraDataValuesSet[i]) { - // emit Lens_Feed_Post_ExtraDataUpdated( - // postId, postParams.extraData[i].key, postParams.extraData[i].value, postParams.extraData[i].value - // ); + emit Lens_Feed_Post_ExtraDataUpdated( + postId, postParams.extraData[i].key, postParams.extraData[i].value, postParams.extraData[i].value + ); } else { - // emit Lens_Feed_Post_ExtraDataAdded( - // postId, postParams.extraData[i].key, postParams.extraData[i].value, postParams.extraData[i].value - // ); + emit Lens_Feed_Post_ExtraDataAdded( + postId, postParams.extraData[i].key, postParams.extraData[i].value, postParams.extraData[i].value + ); } } } diff --git a/contracts/core/primitives/feed/FeedCore.sol b/contracts/core/primitives/feed/FeedCore.sol index 2eee2cc6..ac627b01 100644 --- a/contracts/core/primitives/feed/FeedCore.sol +++ b/contracts/core/primitives/feed/FeedCore.sol @@ -42,7 +42,7 @@ library FeedCore { return uint256(keccak256(abi.encode("evm:", block.chainid, address(this), author, authorPostSequentialId))); } - function _createPost(CreatePostParams calldata postParams) internal returns (uint256, uint256, uint256) { + function _createPost(CreatePostParams memory postParams) internal returns (uint256, uint256, uint256) { uint256 postSequentialId = ++$storage().postCount; uint256 authorPostSequentialId = ++$storage().authorPostCount[postParams.author]; uint256 postId = _generatePostId(postParams.author, authorPostSequentialId); diff --git a/contracts/core/primitives/feed/RuleBasedFeed.sol b/contracts/core/primitives/feed/RuleBasedFeed.sol index 547b9b5c..5b8ffa2a 100644 --- a/contracts/core/primitives/feed/RuleBasedFeed.sol +++ b/contracts/core/primitives/feed/RuleBasedFeed.sol @@ -127,8 +127,8 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { function _addPostRulesAtCreation( uint256 postId, - CreatePostParams calldata postParams, - RuleProcessingParams[] calldata feedRulesParams + CreatePostParams memory postParams, + RuleProcessingParams[] memory feedRulesParams ) internal { _changeEntityRules($postRulesStorage(postId), postId, postParams.ruleChanges, feedRulesParams); } @@ -229,9 +229,9 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { function _processPostCreationOnRootPost( uint256 rootPostId, uint256 postId, - CreatePostParams calldata postParams, - KeyValue[] calldata primitiveCustomParams, - RuleProcessingParams[] calldata postRulesParams + CreatePostParams memory postParams, + KeyValue[] memory primitiveCustomParams, + RuleProcessingParams[] memory postRulesParams ) internal { _processPostCreation( _encodeAndCallProcessCreatePostOnRootPost, @@ -248,9 +248,9 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { function _processPostCreationOnFeed( uint256 postId, - CreatePostParams calldata postParams, - KeyValue[] calldata primitiveCustomParams, - RuleProcessingParams[] calldata feedRulesParams + CreatePostParams memory postParams, + KeyValue[] memory primitiveCustomParams, + RuleProcessingParams[] memory feedRulesParams ) internal { _processPostCreation( _encodeAndCallProcessCreatePostOnFeed, @@ -268,9 +268,9 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { function _processPostEditingOnRootPost( uint256 rootPostId, uint256 postId, - EditPostParams calldata postParams, - KeyValue[] calldata primitiveCustomParams, - RuleProcessingParams[] calldata postRulesParams + EditPostParams memory postParams, + KeyValue[] memory primitiveCustomParams, + RuleProcessingParams[] memory postRulesParams ) internal { _processPostEditing( _encodeAndCallProcessEditPostOnRootPost, @@ -287,9 +287,9 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { function _processPostEditingOnFeed( uint256 postId, - EditPostParams calldata postParams, - KeyValue[] calldata primitiveCustomParams, - RuleProcessingParams[] calldata feedRulesParams + EditPostParams memory postParams, + KeyValue[] memory primitiveCustomParams, + RuleProcessingParams[] memory feedRulesParams ) internal { _processPostEditing( _encodeAndCallProcessEditPostOnFeed, From af083d7eea36d847f7b2866c6cd6506d377e4b7f Mon Sep 17 00:00:00 2001 From: vicnaum Date: Fri, 10 Jan 2025 11:58:43 +0100 Subject: [PATCH 11/41] misc: MigrationFeed made to compile without IR --- contracts/migration/MigrationFeed.sol | 94 ++++++++++++++++----------- 1 file changed, 55 insertions(+), 39 deletions(-) diff --git a/contracts/migration/MigrationFeed.sol b/contracts/migration/MigrationFeed.sol index 82e51cea..8579bcce 100644 --- a/contracts/migration/MigrationFeed.sol +++ b/contracts/migration/MigrationFeed.sol @@ -8,60 +8,76 @@ import {FeedCore as Core, PostStorage} from "contracts/core/primitives/feed/Feed import {Feed} from "contracts/core/primitives/feed/Feed.sol"; import {Errors} from "contracts/core/types/Errors.sol"; +struct PostCreationParams { + uint256 postId; + uint256 rootPostId; + uint256 postSequentialId; + uint256 authorPostSequentialId; + uint80 creationTimestamp; + address source; +} + contract MigrationFeed is Feed { function createPost( - CreatePostParams calldata postParams, - KeyValue[] calldata customParams, - RuleProcessingParams[] calldata feedRulesParams, - RuleProcessingParams[] calldata rootPostRulesParams, - RuleProcessingParams[] calldata quotedPostRulesParams + CreatePostParams memory postParams, + KeyValue[] memory customParams, + RuleProcessingParams[] memory feedRulesParams, + RuleProcessingParams[] memory rootPostRulesParams, + RuleProcessingParams[] memory quotedPostRulesParams ) external override returns (uint256) { - ( - uint256 postId, - uint256 rootPostId, - uint256 postSequentialId, - uint256 authorPostSequentialId, - uint80 creationTimestamp, - address source - ) = abi.decode(customParams[0].value, (uint256, uint256, uint256, uint256, uint80, address)); - // _createPost(postParams, postId, rootPostId, postSequentialId, authorPostSequentialId, creationTimestamp); + PostCreationParams memory postCreationParams = abi.decode(customParams[0].value, (PostCreationParams)); + _createPost( + postParams, + postCreationParams.postId, + postCreationParams.rootPostId, + postCreationParams.postSequentialId, + postCreationParams.authorPostSequentialId, + postCreationParams.creationTimestamp + ); if (customParams.length > 1 && abi.decode(customParams[1].value, (bool))) { // If customParams[1] is present, it must be an ABI-encoded bool representing `forceChecks` - // _forceChecks(postId, rootPostId, postParams); + _forceChecks(postCreationParams.postId, postCreationParams.rootPostId, postParams); } - if (source != address(0)) { + if (postCreationParams.source != address(0)) { // Trust the migrator, no source verification - _setPrimitiveInternalExtraDataForEntity(postId, KeyValue(DATA__SOURCE, abi.encode(source))); - _setPrimitiveInternalExtraDataForEntity(postId, KeyValue(DATA__LAST_UPDATED_SOURCE, abi.encode(source))); + _setPrimitiveInternalExtraDataForEntity( + postCreationParams.postId, KeyValue(DATA__SOURCE, abi.encode(postCreationParams.source)) + ); + _setPrimitiveInternalExtraDataForEntity( + postCreationParams.postId, KeyValue(DATA__LAST_UPDATED_SOURCE, abi.encode(postCreationParams.source)) + ); } - // emit Lens_Feed_PostCreated( - // source, - // postId, - // authorPostSequentialId, - // rootPostId, - // quotedPostRulesParams, - // rootPostRulesParams, - // feedRulesParams, - // customParams, - // postParams, - // postParams.author - // ); + emit Lens_Feed_PostCreated( + postCreationParams.postId, + postParams.author, + postCreationParams.authorPostSequentialId, + postCreationParams.rootPostId, + postParams, + customParams, + feedRulesParams, + rootPostRulesParams, + quotedPostRulesParams, + postCreationParams.source + ); - // for (uint256 i = 0; i < postParams.extraData.length; i++) { - // _setEntityExtraData(postId, postParams.extraData[i]); - // emit Lens_Feed_Post_ExtraDataAdded( - // postId, postParams.extraData[i].key, postParams.extraData[i].value, postParams.extraData[i].value - // ); - // } - return postId; + for (uint256 i = 0; i < postParams.extraData.length; i++) { + _setEntityExtraData(postCreationParams.postId, postParams.extraData[i]); + emit Lens_Feed_Post_ExtraDataAdded( + postCreationParams.postId, + postParams.extraData[i].key, + postParams.extraData[i].value, + postParams.extraData[i].value + ); + } + return postCreationParams.postId; } // Overriding the FeedCore function _createPost( - CreatePostParams calldata postParams, + CreatePostParams memory postParams, uint256 postId, uint256 rootPostId, uint256 postSequentialId, @@ -83,7 +99,7 @@ contract MigrationFeed is Feed { _newPost.lastUpdatedTimestamp = creationTimestamp; } - function _forceChecks(uint256 postId, uint256 rootPostId, CreatePostParams calldata postParams) internal view { + function _forceChecks(uint256 postId, uint256 rootPostId, CreatePostParams memory postParams) internal view { // TODO: Check if the rootPostId == postId case (not a reply, not a repost) if (rootPostId != postId) { require(Core._postExists(rootPostId), Errors.DoesNotExist()); From 0aad9f25c6fbb0f51f31301919c1debb361281c8 Mon Sep 17 00:00:00 2001 From: vicnaum Date: Fri, 10 Jan 2025 12:21:17 +0100 Subject: [PATCH 12/41] misc: LensFactory made to compile without IR --- .../extensions/factories/LensFactory.sol | 250 ++++++++++-------- 1 file changed, 140 insertions(+), 110 deletions(-) diff --git a/contracts/extensions/factories/LensFactory.sol b/contracts/extensions/factories/LensFactory.sol index eab6ef0b..83ddf8f2 100644 --- a/contracts/extensions/factories/LensFactory.sol +++ b/contracts/extensions/factories/LensFactory.sol @@ -87,114 +87,144 @@ contract LensFactory { GROUP_GATED_FEED_RULE = groupGatedFeedRule; } - // // TODO: This function belongs to an App probably. - // function createAccountWithUsernameFree( - // string calldata metadataURI, - // address owner, - // address[] calldata accountManagers, - // AccountManagerPermissions[] calldata accountManagersPermissions, - // address namespacePrimitiveAddress, - // string calldata username, - // SourceStamp calldata accountCreationSourceStamp, - // KeyValue[] calldata createUsernameCustomParams, - // RuleProcessingParams[] calldata createUsernameRuleProcessingParams, - // KeyValue[] calldata assignUsernameCustomParams, - // RuleProcessingParams[] calldata unassignAccountRuleProcessingParams, - // RuleProcessingParams[] calldata assignRuleProcessingParams, - // KeyValue[] calldata accountExtraData, - // KeyValue[] calldata usernameExtraData - // ) external returns (address) { - // address account = ACCOUNT_FACTORY.deployAccount( - // address(this), - // metadataURI, - // accountManagers, - // accountManagersPermissions, - // accountCreationSourceStamp, - // accountExtraData - // ); - // INamespace namespacePrimitive = INamespace(namespacePrimitiveAddress); - // bytes memory txData = abi.encodeCall( - // namespacePrimitive.createUsername, - // (account, username, createUsernameCustomParams, createUsernameRuleProcessingParams, usernameExtraData) - // ); - // IAccount(payable(account)).executeTransaction(namespacePrimitiveAddress, uint256(0), txData); - // txData = abi.encodeCall( - // namespacePrimitive.assignUsername, - // ( - // account, - // username, - // assignUsernameCustomParams, - // unassignAccountRuleProcessingParams, - // new RuleProcessingParams[](0), - // assignRuleProcessingParams - // ) - // ); - // IAccount(payable(account)).executeTransaction(namespacePrimitiveAddress, uint256(0), txData); - // IOwnable(account).transferOwnership(owner); - // return account; - // } - - // function createGroupWithFeed( - // address owner, - // address[] calldata admins, - // string calldata groupMetadataURI, - // RuleChange[] calldata groupRules, - // KeyValue[] calldata groupExtraData, - // string calldata feedMetadataURI, - // RuleChange[] calldata feedRules, - // KeyValue[] calldata feedExtraData - // ) external returns (address, address) { - // IRoleBasedAccessControl groupAccessControl = _deployAccessControl(owner, admins); - - // address group = GROUP_FACTORY.deployGroup( - // groupMetadataURI, - // TEMPORARY_ACCESS_CONTROL, - // owner, - // _injectRuleAccessControl(groupRules, address(groupAccessControl)), - // groupExtraData - // ); - - // RuleChange[] memory modifiedFeedRules = new RuleChange[](feedRules.length + 2); - - // RuleSelectorChange[] memory selectorChanges = new RuleSelectorChange[](1); - // // Both rules only operate on IFeedRule.processCreatePost.selector (at least at the moment of writing this) - // selectorChanges[0] = - // RuleSelectorChange({ruleSelector: IFeedRule.processCreatePost.selector, isRequired: true, enabled: true}); - - // modifiedFeedRules[0] = RuleChange({ - // ruleAddress: ACCOUNT_BLOCKING_RULE, - // configSalt: bytes32(0), - // configurationChanges: RuleConfigurationChange({configure: true, ruleParams: new KeyValue[](0)}), - // selectorChanges: selectorChanges - // }); - - // KeyValue[] memory groupGatedRuleParams = new KeyValue[](1); - // groupGatedRuleParams[0] = KeyValue({key: PARAM__GROUP, value: abi.encode(group)}); - - // modifiedFeedRules[1] = RuleChange({ - // ruleAddress: GROUP_GATED_FEED_RULE, - // configSalt: bytes32(0), - // configurationChanges: RuleConfigurationChange({configure: true, ruleParams: groupGatedRuleParams}), - // selectorChanges: selectorChanges - // }); - - // IRoleBasedAccessControl feedAccessControl = _deployAccessControl(owner, admins); - - // for (uint256 i = 0; i < feedRules.length; i++) { - // require(feedRules[i].ruleAddress != ACCOUNT_BLOCKING_RULE, Errors.DuplicatedValue()); - // require(feedRules[i].ruleAddress != GROUP_GATED_FEED_RULE, Errors.DuplicatedValue()); - // modifiedFeedRules[i + 2] = _injectRuleAccessControl(feedRules[i], address(feedAccessControl)); - // } - - // address feed = - // FEED_FACTORY.deployFeed(feedMetadataURI, feedAccessControl, owner, modifiedFeedRules, feedExtraData); - - // KeyValue[] memory groupExtraDataWithFeed = new KeyValue[](1); - // groupExtraDataWithFeed[0] = KeyValue({key: DATA__GROUP_LINKED_FEED, value: abi.encode(feed)}); - // IGroup(group).setExtraData(groupExtraDataWithFeed); - // AccessControlled(group).setAccessControl(groupAccessControl); - // return (group, feed); - // } + struct CreateAccountParams { + string metadataURI; + address owner; + address[] accountManagers; + AccountManagerPermissions[] accountManagersPermissions; + SourceStamp accountCreationSourceStamp; + KeyValue[] accountExtraData; + } + + struct CreateUsernameParams { + string username; + KeyValue[] createUsernameCustomParams; + RuleProcessingParams[] createUsernameRuleProcessingParams; + KeyValue[] assignUsernameCustomParams; + RuleProcessingParams[] unassignAccountRuleProcessingParams; + RuleProcessingParams[] assignRuleProcessingParams; + KeyValue[] usernameExtraData; + } + + // TODO: This function belongs to an App probably. + function createAccountWithUsernameFree( + address namespacePrimitiveAddress, + CreateAccountParams calldata accountParams, + CreateUsernameParams calldata usernameParams + ) external returns (address) { + address account = ACCOUNT_FACTORY.deployAccount( + address(this), + accountParams.metadataURI, + accountParams.accountManagers, + accountParams.accountManagersPermissions, + accountParams.accountCreationSourceStamp, + accountParams.accountExtraData + ); + INamespace namespacePrimitive = INamespace(namespacePrimitiveAddress); + bytes memory txData = abi.encodeCall( + namespacePrimitive.createUsername, + ( + account, + usernameParams.username, + usernameParams.createUsernameCustomParams, + usernameParams.createUsernameRuleProcessingParams, + usernameParams.usernameExtraData + ) + ); + IAccount(payable(account)).executeTransaction(namespacePrimitiveAddress, uint256(0), txData); + txData = abi.encodeCall( + namespacePrimitive.assignUsername, + ( + account, + usernameParams.username, + usernameParams.assignUsernameCustomParams, + usernameParams.unassignAccountRuleProcessingParams, + new RuleProcessingParams[](0), + usernameParams.assignRuleProcessingParams + ) + ); + IAccount(payable(account)).executeTransaction(namespacePrimitiveAddress, uint256(0), txData); + IOwnable(account).transferOwnership(accountParams.owner); + return account; + } + + struct CreateGroupWithFeedParams { + address group; + IRoleBasedAccessControl groupAccessControl; + IRoleBasedAccessControl feedAccessControl; + RuleChange[] modifiedFeedRules; + KeyValue[] feedExtraData; + } + + function createGroupWithFeed( + address owner, + address[] memory admins, + string memory groupMetadataURI, + RuleChange[] memory groupRules, + KeyValue[] memory groupExtraData, + string memory feedMetadataURI, + RuleChange[] memory feedRules, + KeyValue[] memory feedExtraData + ) external returns (address, address) { + CreateGroupWithFeedParams memory s; + s.feedExtraData = feedExtraData; + s.feedAccessControl = _deployAccessControl(owner, admins); + + { + s.groupAccessControl = _deployAccessControl(owner, admins); + + s.group = GROUP_FACTORY.deployGroup( + groupMetadataURI, + TEMPORARY_ACCESS_CONTROL, + owner, + _injectRuleAccessControl(groupRules, address(s.groupAccessControl)), + groupExtraData + ); + } + + s.modifiedFeedRules = new RuleChange[](feedRules.length + 2); + + { + RuleSelectorChange[] memory selectorChanges = new RuleSelectorChange[](1); + // Both rules only operate on IFeedRule.processCreatePost.selector (at least at the moment of writing this) + selectorChanges[0] = + RuleSelectorChange({ruleSelector: IFeedRule.processCreatePost.selector, isRequired: true, enabled: true}); + + s.modifiedFeedRules[0] = RuleChange({ + ruleAddress: ACCOUNT_BLOCKING_RULE, + configSalt: bytes32(0), + configurationChanges: RuleConfigurationChange({configure: true, ruleParams: new KeyValue[](0)}), + selectorChanges: selectorChanges + }); + + KeyValue[] memory groupGatedRuleParams = new KeyValue[](1); + groupGatedRuleParams[0] = KeyValue({key: PARAM__GROUP, value: abi.encode(s.group)}); + + s.modifiedFeedRules[1] = RuleChange({ + ruleAddress: GROUP_GATED_FEED_RULE, + configSalt: bytes32(0), + configurationChanges: RuleConfigurationChange({configure: true, ruleParams: groupGatedRuleParams}), + selectorChanges: selectorChanges + }); + } + + { + for (uint256 i = 0; i < feedRules.length; i++) { + require(feedRules[i].ruleAddress != ACCOUNT_BLOCKING_RULE, Errors.DuplicatedValue()); + require(feedRules[i].ruleAddress != GROUP_GATED_FEED_RULE, Errors.DuplicatedValue()); + s.modifiedFeedRules[i + 2] = _injectRuleAccessControl(feedRules[i], address(s.feedAccessControl)); + } + } + + address feed = + FEED_FACTORY.deployFeed(feedMetadataURI, s.feedAccessControl, owner, s.modifiedFeedRules, s.feedExtraData); + + KeyValue[] memory groupExtraDataWithFeed = new KeyValue[](1); + groupExtraDataWithFeed[0] = KeyValue({key: DATA__GROUP_LINKED_FEED, value: abi.encode(feed)}); + IGroup(s.group).setExtraData(groupExtraDataWithFeed); + AccessControlled(s.group).setAccessControl(s.groupAccessControl); + return (s.group, feed); + } function deployAccount( string calldata metadataURI, @@ -322,7 +352,7 @@ contract LensFactory { return rule; } - function _injectRuleAccessControl(RuleChange[] calldata rules, address accessControl) + function _injectRuleAccessControl(RuleChange[] memory rules, address accessControl) internal pure returns (RuleChange[] memory) @@ -334,7 +364,7 @@ contract LensFactory { return modifiedRules; } - function _prepareRules(RuleChange[] calldata rules, bytes4 ruleSelector, address accessControl) + function _prepareRules(RuleChange[] memory rules, bytes4 ruleSelector, address accessControl) internal view returns (RuleChange[] memory) From cc4fe7eb1fb29e3ac417fb47223a3064e6793ae4 Mon Sep 17 00:00:00 2001 From: vicnaum Date: Fri, 10 Jan 2025 12:23:05 +0100 Subject: [PATCH 13/41] misc: LensFactory tests made to compile without IR --- .../extensions/factories/LensFactory.sol | 38 +++++++++--------- test/factories/LensFactory.t.sol | 40 +++++++++++-------- 2 files changed, 42 insertions(+), 36 deletions(-) diff --git a/contracts/extensions/factories/LensFactory.sol b/contracts/extensions/factories/LensFactory.sol index 83ddf8f2..50db4d41 100644 --- a/contracts/extensions/factories/LensFactory.sol +++ b/contracts/extensions/factories/LensFactory.sol @@ -52,6 +52,25 @@ bytes32 constant DATA__GROUP_LINKED_FEED = 0xfec1c12508813d27a0104e0d1f0ad007b92 /// @custom:keccak lens.param.accessControl bytes32 constant PARAM__ACCESS_CONTROL = 0xcf3b0fab90208e4185bf857e0f943f6672abffb7d0898e0750beeeb991ae35fa; +struct CreateAccountParams { + string metadataURI; + address owner; + address[] accountManagers; + AccountManagerPermissions[] accountManagersPermissions; + SourceStamp accountCreationSourceStamp; + KeyValue[] accountExtraData; +} + +struct CreateUsernameParams { + string username; + KeyValue[] createUsernameCustomParams; + RuleProcessingParams[] createUsernameRuleProcessingParams; + KeyValue[] assignUsernameCustomParams; + RuleProcessingParams[] unassignAccountRuleProcessingParams; + RuleProcessingParams[] assignRuleProcessingParams; + KeyValue[] usernameExtraData; +} + contract LensFactory { AccessControlFactory internal immutable ACCESS_CONTROL_FACTORY; AccountFactory internal immutable ACCOUNT_FACTORY; @@ -87,25 +106,6 @@ contract LensFactory { GROUP_GATED_FEED_RULE = groupGatedFeedRule; } - struct CreateAccountParams { - string metadataURI; - address owner; - address[] accountManagers; - AccountManagerPermissions[] accountManagersPermissions; - SourceStamp accountCreationSourceStamp; - KeyValue[] accountExtraData; - } - - struct CreateUsernameParams { - string username; - KeyValue[] createUsernameCustomParams; - RuleProcessingParams[] createUsernameRuleProcessingParams; - KeyValue[] assignUsernameCustomParams; - RuleProcessingParams[] unassignAccountRuleProcessingParams; - RuleProcessingParams[] assignRuleProcessingParams; - KeyValue[] usernameExtraData; - } - // TODO: This function belongs to an App probably. function createAccountWithUsernameFree( address namespacePrimitiveAddress, diff --git a/test/factories/LensFactory.t.sol b/test/factories/LensFactory.t.sol index 50cd0b3d..dd3cebbc 100644 --- a/test/factories/LensFactory.t.sol +++ b/test/factories/LensFactory.t.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.26; import "forge-std/Test.sol"; -import {LensFactory} from "@extensions/factories/LensFactory.sol"; +import {LensFactory, CreateAccountParams, CreateUsernameParams} from "@extensions/factories/LensFactory.sol"; import {AccountFactory} from "@extensions/factories/AccountFactory.sol"; import {AppFactory} from "@extensions/factories/AppFactory.sol"; import {GroupFactory} from "@extensions/factories/GroupFactory.sol"; @@ -50,22 +50,28 @@ contract LensFactoryTest is Test, BaseDeployments { } function testCreateAccountWithUsernameFree() public { - // lensFactory.createAccountWithUsernameFree({ - // metadataURI: "someMetadataURI", - // owner: address(this), - // accountManagers: _emptyAddressArray(), - // accountManagersPermissions: new AccountManagerPermissions[](0), - // namespacePrimitiveAddress: address(namespace), - // username: "myTestUsername", - // accountCreationSourceStamp: _emptySourceStamp(), - // createUsernameCustomParams: _emptyKeyValueArray(), - // createUsernameRuleProcessingParams: _emptyRuleProcessingParamsArray(), - // assignUsernameCustomParams: _emptyKeyValueArray(), - // unassignAccountRuleProcessingParams: _emptyRuleProcessingParamsArray(), - // assignRuleProcessingParams: _emptyRuleProcessingParamsArray(), - // accountExtraData: _emptyKeyValueArray(), - // usernameExtraData: _emptyKeyValueArray() - // }); + CreateAccountParams memory accountParams = CreateAccountParams({ + metadataURI: "someMetadataURI", + owner: address(this), + accountManagers: _emptyAddressArray(), + accountManagersPermissions: new AccountManagerPermissions[](0), + accountCreationSourceStamp: _emptySourceStamp(), + accountExtraData: _emptyKeyValueArray() + }); + CreateUsernameParams memory usernameParams = CreateUsernameParams({ + username: "myTestUsername", + createUsernameCustomParams: _emptyKeyValueArray(), + createUsernameRuleProcessingParams: _emptyRuleProcessingParamsArray(), + assignUsernameCustomParams: _emptyKeyValueArray(), + unassignAccountRuleProcessingParams: _emptyRuleProcessingParamsArray(), + assignRuleProcessingParams: _emptyRuleProcessingParamsArray(), + usernameExtraData: _emptyKeyValueArray() + }); + lensFactory.createAccountWithUsernameFree({ + accountParams: accountParams, + namespacePrimitiveAddress: address(namespace), + usernameParams: usernameParams + }); } function testGraphFollowWithFactorySetup() public { From cef1882150f371644d6b620f89fbdb69d262401f Mon Sep 17 00:00:00 2001 From: vicnaum Date: Sat, 11 Jan 2025 22:25:26 +0100 Subject: [PATCH 14/41] misc: Namespace code updated to give better revert reasons for non-existing usernames --- contracts/core/interfaces/INamespace.sol | 6 +++++ .../core/primitives/namespace/Namespace.sol | 23 +++++++++++++++---- .../primitives/namespace/NamespaceCore.sol | 20 +--------------- 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/contracts/core/interfaces/INamespace.sol b/contracts/core/interfaces/INamespace.sol index 31d9bbef..3dbc489a 100644 --- a/contracts/core/interfaces/INamespace.sol +++ b/contracts/core/interfaces/INamespace.sol @@ -118,4 +118,10 @@ interface INamespace is IMetadataBased { function getExtraData(bytes32 key) external view returns (bytes memory); function getUsernameExtraData(string calldata username, bytes32 key) external view returns (bytes memory); + + function exists(string calldata username) external view returns (bool); + + function exists(uint256 tokenId) external view returns (bool); + + function getUsernameTokenId(string calldata username) external view returns (uint256); } diff --git a/contracts/core/primitives/namespace/Namespace.sol b/contracts/core/primitives/namespace/Namespace.sol index 865e0e88..5c2e2395 100644 --- a/contracts/core/primitives/namespace/Namespace.sol +++ b/contracts/core/primitives/namespace/Namespace.sol @@ -143,7 +143,7 @@ contract Namespace is RuleProcessingParams[] calldata removalRuleProcessingParams ) external override { uint256 id = _computeId(username); - address owner = _ownerOf(id); + address owner = ownerOf(id); require(msg.sender == owner, Errors.InvalidMsgSender()); // msg.sender must be the owner of the username _processRemoval(msg.sender, username, customParams, removalRuleProcessingParams); address source = _processSourceStamp(id, customParams); @@ -161,9 +161,11 @@ contract Namespace is RuleProcessingParams[] calldata unassignUsernameRuleProcessingParams, RuleProcessingParams[] calldata assignRuleProcessingParams ) external override { - require(msg.sender == account, Errors.InvalidMsgSender()); uint256 id = _computeId(username); - require(account == _ownerOf(id), Errors.InvalidMsgSender()); // account should own the tokenized username + // account should own the tokenized username and be the msg.sender + require(msg.sender == ownerOf(id) && msg.sender == account, Errors.InvalidMsgSender()); + // Check if username is not already assigned to this account + require(account != Core.$storage().usernameToAccount[username], Errors.RedundantStateChange()); address source = _processSourceStamp(id, customParams); _unassignIfAssigned(account, customParams, unassignAccountRuleProcessingParams, source); _unassignIfAssigned(username, customParams, unassignUsernameRuleProcessingParams, source); @@ -179,7 +181,7 @@ contract Namespace is ) external override { address account = Core.$storage().usernameToAccount[username]; uint256 id = _computeId(username); - require(msg.sender == account || msg.sender == _ownerOf(id), Errors.InvalidMsgSender()); + require(msg.sender == ownerOf(id) || msg.sender == account, Errors.InvalidMsgSender()); Core._unassignUsername(username); _processUnassigning(msg.sender, account, username, customParams, ruleProcessingParams); address source = _processSourceStamp(id, customParams); @@ -299,4 +301,17 @@ contract Namespace is address owner = ownerOf(tokenId); return _getEntityExtraData(owner, tokenId, key); } + + function exists(string calldata username) external view override returns (bool) { + uint256 tokenId = _computeId(username); + return _exists(tokenId); + } + + function exists(uint256 tokenId) external view override returns (bool) { + return _exists(tokenId); + } + + function getUsernameTokenId(string calldata username) external view returns (uint256) { + return _computeId(username); + } } diff --git a/contracts/core/primitives/namespace/NamespaceCore.sol b/contracts/core/primitives/namespace/NamespaceCore.sol index 9570312e..f0af1289 100644 --- a/contracts/core/primitives/namespace/NamespaceCore.sol +++ b/contracts/core/primitives/namespace/NamespaceCore.sol @@ -23,25 +23,7 @@ library NamespaceCore { } } - // External functions - Use these functions to be called through DELEGATECALL - - function createUsername(string memory username) external { - _createUsername(username); - } - - function removeUsername(string memory username) external { - _removeUsername(username); - } - - function assignUsername(address account, string memory username) external { - _assignUsername(account, username); - } - - function unassignUsername(string memory username) external { - _unassignUsername(username); - } - - // Internal functions - Use these functions to be called as an inlined library + // Internal functions function _createUsername(string memory username) internal { require(!$storage().usernameExists[username], Errors.AlreadyExists()); // Username must not exist yet From 8198261dc740440ccdb4629c206da39e1d46f665 Mon Sep 17 00:00:00 2001 From: vicnaum Date: Sat, 11 Jan 2025 22:25:54 +0100 Subject: [PATCH 15/41] test: coverage skipper added to deploy script --- script/Deploy.s.sol | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/script/Deploy.s.sol b/script/Deploy.s.sol index c31608c4..e2a9be29 100644 --- a/script/Deploy.s.sol +++ b/script/Deploy.s.sol @@ -35,6 +35,10 @@ import {AccountBlockingRule} from "contracts/rules/base/AccountBlockingRule.sol" import {GroupGatedFeedRule} from "contracts/rules/feed/GroupGatedFeedRule.sol"; contract MyScript is Script { + function testMyScript() public { + // Prevents being counted in Foundry Coverage + } + IAccessControl simpleAccessControl; ITokenURIProvider simpleTokenURIProvider; address proxyAdminLock; From e6ed3088db0e092d0e689e3cd6ba59ca3b504156 Mon Sep 17 00:00:00 2001 From: vicnaum Date: Sat, 11 Jan 2025 22:28:37 +0100 Subject: [PATCH 16/41] test: coverage scripts added --- .gitignore | 2 ++ coverage.sh | 4 ++++ package.json | 2 ++ 3 files changed, 8 insertions(+) create mode 100644 coverage.sh diff --git a/.gitignore b/.gitignore index 11ebfea6..df40ead6 100644 --- a/.gitignore +++ b/.gitignore @@ -133,3 +133,5 @@ dist deployment-zk/* !deployment-zk/lensSepoliaTestnet/ cache_forge/solidity-files-cache.json + +lcov.info diff --git a/coverage.sh b/coverage.sh new file mode 100644 index 00000000..59b9d81a --- /dev/null +++ b/coverage.sh @@ -0,0 +1,4 @@ +rm -fr coverage lcov.info +mkdir -p coverage +forge coverage --report lcov +genhtml --ignore-errors inconsistent --ignore-errors corrupt --ignore-errors category --rc derive_function_end_line=0 lcov.info -o coverage/html --branch-coverage >/dev/null 2>&1 || { echo "Error generating coverage report"; exit 1; } diff --git a/package.json b/package.json index 48809f33..bb3a1615 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,8 @@ "compile": "hardhat compile", "clean": "hardhat clean", "test": "hardhat test --network hardhat", + "coverage": "forge coverage", + "coverage:report": "bash coverage.sh", "prepare": "husky", "format": "forge fmt", "prod:abis": "npm run abis && cp -r out/abis ./ABIs", From 0da8a9947c8c47afd192d86affc504ed3d7a51b8 Mon Sep 17 00:00:00 2001 From: vicnaum Date: Tue, 14 Jan 2025 16:01:48 +0100 Subject: [PATCH 17/41] misc: added checks for address(0) to GraphCore --- contracts/core/primitives/graph/GraphCore.sol | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/contracts/core/primitives/graph/GraphCore.sol b/contracts/core/primitives/graph/GraphCore.sol index fb0292fc..31854742 100644 --- a/contracts/core/primitives/graph/GraphCore.sol +++ b/contracts/core/primitives/graph/GraphCore.sol @@ -31,6 +31,8 @@ library GraphCore { internal returns (uint256) { + require(followerAccount != address(0), Errors.InvalidParameter()); + require(accountToFollow != address(0), Errors.InvalidParameter()); require(followerAccount != accountToFollow, Errors.Self()); require($storage().follows[followerAccount][accountToFollow].id == 0, Errors.CannotFollowAgain()); if (followId == 0) { @@ -47,6 +49,8 @@ library GraphCore { } function _unfollow(address followerAccount, address accountToUnfollow) internal returns (uint256) { + require(followerAccount != address(0), Errors.InvalidParameter()); + require(accountToUnfollow != address(0), Errors.InvalidParameter()); uint256 followId = $storage().follows[followerAccount][accountToUnfollow].id; require(followId != 0, Errors.NotFollowing()); // Must be following $storage().followersCount[accountToUnfollow]--; From 20e2200d6a46cb7cac010eb4e07839d1991c9e7d Mon Sep 17 00:00:00 2001 From: vicnaum Date: Tue, 14 Jan 2025 16:02:04 +0100 Subject: [PATCH 18/41] fix: MigrationGraph fixed --- contracts/migration/MigrationGraph.sol | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/contracts/migration/MigrationGraph.sol b/contracts/migration/MigrationGraph.sol index e990bdb1..0067c3e5 100644 --- a/contracts/migration/MigrationGraph.sol +++ b/contracts/migration/MigrationGraph.sol @@ -6,6 +6,8 @@ import {GraphCore as Core} from "contracts/core/primitives/graph/GraphCore.sol"; import {Graph} from "contracts/core/primitives/graph/Graph.sol"; import {RuleProcessingParams, KeyValue} from "contracts/core/types/Types.sol"; import {IAccessControl} from "contracts/core/interfaces/IAccessControl.sol"; +import {Follow} from "contracts/core/interfaces/IGraph.sol"; +import {Errors} from "contracts/core/types/Errors.sol"; /** * Special Graph implementation to allow data migrations from Lens V2 to Lens V3 @@ -20,7 +22,7 @@ contract MigrationGraph is Graph { KeyValue[] calldata extraData ) external override returns (uint256) { (uint256 followId, uint256 timestamp) = abi.decode(customParams[0].value, (uint256, uint256)); - Core._follow(followerAccount, accountToFollow, followId, timestamp); + _followWithoutChecks(followerAccount, accountToFollow, followId, timestamp); emit Lens_Graph_Followed( followerAccount, accountToFollow, @@ -33,4 +35,19 @@ contract MigrationGraph is Graph { ); return followId; } + + function _followWithoutChecks(address followerAccount, address accountToFollow, uint256 followId, uint256 timestamp) + internal + { + require(followerAccount != accountToFollow, Errors.Self()); + require(followId != 0, Errors.InvalidParameter()); + require(followerAccount != address(0), Errors.InvalidParameter()); + require(accountToFollow != address(0), Errors.InvalidParameter()); + require(Core.$storage().follows[followerAccount][accountToFollow].id == 0, Errors.CannotFollowAgain()); + require(Core.$storage().followers[accountToFollow][followId] == address(0), Errors.AlreadyExists()); + Core.$storage().follows[followerAccount][accountToFollow] = Follow({id: followId, timestamp: timestamp}); + Core.$storage().followers[accountToFollow][followId] = followerAccount; + Core.$storage().followersCount[accountToFollow]++; + Core.$storage().followingCount[followerAccount]++; + } } From 283d303af6eb84e6a71e06aca75d342e782e40b2 Mon Sep 17 00:00:00 2001 From: vicnaum Date: Tue, 14 Jan 2025 17:42:30 +0100 Subject: [PATCH 19/41] fix: MigrationFeed extradata saving fix --- contracts/migration/MigrationFeed.sol | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/contracts/migration/MigrationFeed.sol b/contracts/migration/MigrationFeed.sol index 8579bcce..6bc8387a 100644 --- a/contracts/migration/MigrationFeed.sol +++ b/contracts/migration/MigrationFeed.sol @@ -64,7 +64,7 @@ contract MigrationFeed is Feed { ); for (uint256 i = 0; i < postParams.extraData.length; i++) { - _setEntityExtraData(postCreationParams.postId, postParams.extraData[i]); + _setExtraData(postParams.author, postCreationParams.postId, postParams.extraData[i]); emit Lens_Feed_Post_ExtraDataAdded( postCreationParams.postId, postParams.extraData[i].key, @@ -84,8 +84,14 @@ contract MigrationFeed is Feed { uint256 authorPostSequentialId, uint80 creationTimestamp ) internal { - Core.$storage().postCount = postSequentialId; - Core.$storage().authorPostCount[postParams.author] = authorPostSequentialId; + require(postParams.author != address(0), Errors.InvalidParameter()); + require(postId != 0, Errors.InvalidParameter()); + require(postSequentialId != 0, Errors.InvalidParameter()); + require(authorPostSequentialId != 0, Errors.InvalidParameter()); + require(creationTimestamp != 0, Errors.InvalidParameter()); + + Core.$storage().postCount++; + Core.$storage().authorPostCount[postParams.author]++; PostStorage storage _newPost = Core.$storage().posts[postId]; _newPost.author = postParams.author; _newPost.authorPostSequentialId = authorPostSequentialId; From f4b42d5e7ae99f16681b5f36b0cb092dc3d906ea Mon Sep 17 00:00:00 2001 From: Alan Donoso Naumczuk Date: Tue, 14 Jan 2025 16:03:15 -0300 Subject: [PATCH 20/41] misc: Better error throwing during enable/disable rule selectors --- contracts/core/libraries/RulesLib.sol | 26 +++++++++++--------------- contracts/core/types/Errors.sol | 1 + 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/contracts/core/libraries/RulesLib.sol b/contracts/core/libraries/RulesLib.sol index 15547514..389b5ae7 100644 --- a/contracts/core/libraries/RulesLib.sol +++ b/contracts/core/libraries/RulesLib.sol @@ -59,22 +59,27 @@ library RulesLib { bytes4 ruleSelector ) internal { require(rulesStorage.isConfigured[ruleAddress][configSalt], Errors.RuleNotConfigured()); - require( - !_isSelectorAlreadyEnabled(rulesStorage, ruleSelector, ruleAddress, configSalt), - Errors.RedundantStateChange() - ); + if (rulesStorage.ruleStates[ruleSelector][ruleAddress][configSalt].isEnabled) { + if (rulesStorage.ruleStates[ruleSelector][ruleAddress][configSalt].isRequired == isRequired) { + revert Errors.RedundantStateChange(); + } else { + revert Errors.SelectorEnabledForDifferentRuleType(); + } + } _addRuleSelectorToStorage(rulesStorage, ruleSelector, ruleAddress, configSalt, isRequired); } function disableRuleSelector( RulesStorage storage rulesStorage, - bool, /* isRequired */ + bool isRequired, address ruleAddress, bytes32 configSalt, bytes4 ruleSelector ) internal { + require(rulesStorage.ruleStates[ruleSelector][ruleAddress][configSalt].isEnabled, Errors.RedundantStateChange()); require( - _isSelectorAlreadyEnabled(rulesStorage, ruleSelector, ruleAddress, configSalt), Errors.RedundantStateChange() + rulesStorage.ruleStates[ruleSelector][ruleAddress][configSalt].isRequired == isRequired, + Errors.SelectorEnabledForDifferentRuleType() ); _removeRuleSelectorFromStorage(rulesStorage, ruleSelector, ruleAddress, configSalt); } @@ -148,13 +153,4 @@ library RulesLib { rules.pop(); delete rulesStorage.ruleStates[ruleSelector][ruleAddress][configSalt]; } - - function _isSelectorAlreadyEnabled( - RulesStorage storage rulesStorage, - bytes4 ruleSelector, - address ruleAddress, - bytes32 configSalt - ) private view returns (bool) { - return rulesStorage.ruleStates[ruleSelector][ruleAddress][configSalt].isEnabled; - } } diff --git a/contracts/core/types/Errors.sol b/contracts/core/types/Errors.sol index 94651071..1c60ac68 100644 --- a/contracts/core/types/Errors.sol +++ b/contracts/core/types/Errors.sol @@ -36,6 +36,7 @@ library Errors { error RedundantStateChange(); error RequiredRuleReverted(); error RuleNotConfigured(); + error SelectorEnabledForDifferentRuleType(); error Self(); error SingleAnyOfRule(); error UnexpectedContractImpl(); From 738c509fd32c56cc1a897611f1f3aa7a1f6a0274 Mon Sep 17 00:00:00 2001 From: Alan Donoso Naumczuk Date: Tue, 14 Jan 2025 16:11:37 -0300 Subject: [PATCH 21/41] misc: SkipTokenGate refactored to a more generic SkipGate permission --- contracts/rules/feed/TokenGatedFeedRule.sol | 8 ++++---- contracts/rules/follow/TokenGatedFollowRule.sol | 8 ++++---- contracts/rules/graph/GroupGatedGraphRule.sol | 8 ++++---- contracts/rules/graph/TokenGatedGraphRule.sol | 8 ++++---- contracts/rules/group/TokenGatedGroupRule.sol | 8 ++++---- contracts/rules/namespace/TokenGatedNamespaceRule.sol | 8 ++++---- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/contracts/rules/feed/TokenGatedFeedRule.sol b/contracts/rules/feed/TokenGatedFeedRule.sol index f88c2d97..3c1cdb32 100644 --- a/contracts/rules/feed/TokenGatedFeedRule.sol +++ b/contracts/rules/feed/TokenGatedFeedRule.sol @@ -15,8 +15,8 @@ contract TokenGatedFeedRule is TokenGatedRule, IFeedRule { using AccessControlLib for IAccessControl; using AccessControlLib for address; - /// @custom:keccak lens.permission.SkipTokenGate - uint256 constant PID__SKIP_TOKEN_GATE = uint256(0x42073514d6ebc3c4c46bdc33d53105f5c563a0d184e86952704eb3e7b74ec1ae); + /// @custom:keccak lens.permission.SkipGate + uint256 constant PID__SKIP_GATE = uint256(0xeb7f30e4c97d5211e2534aa42375c26931bd55b57a8101e5eb7918daead714eb); /// @custom:keccak lens.param.accessControl bytes32 constant PARAM__ACCESS_CONTROL = 0xcf3b0fab90208e4185bf857e0f943f6672abffb7d0898e0750beeeb991ae35fa; @@ -29,7 +29,7 @@ contract TokenGatedFeedRule is TokenGatedRule, IFeedRule { mapping(address => mapping(bytes32 => Configuration)) internal _configuration; constructor(string memory metadataURI) TokenGatedRule(metadataURI) { - emit Events.Lens_PermissionId_Available(PID__SKIP_TOKEN_GATE, "lens.permission.SkipTokenGate"); + emit Events.Lens_PermissionId_Available(PID__SKIP_GATE, "lens.permission.SkipGate"); } function configure(bytes32 configSalt, KeyValue[] calldata ruleParams) external override { @@ -86,7 +86,7 @@ contract TokenGatedFeedRule is TokenGatedRule, IFeedRule { TokenGateConfiguration memory tokenGateConfiguration, address account ) internal view { - if (!accessControl.hasAccess(account, PID__SKIP_TOKEN_GATE)) { + if (!accessControl.hasAccess(account, PID__SKIP_GATE)) { _validateTokenBalance(tokenGateConfiguration, account); } } diff --git a/contracts/rules/follow/TokenGatedFollowRule.sol b/contracts/rules/follow/TokenGatedFollowRule.sol index b06267fc..da408b29 100644 --- a/contracts/rules/follow/TokenGatedFollowRule.sol +++ b/contracts/rules/follow/TokenGatedFollowRule.sol @@ -13,8 +13,8 @@ contract TokenGatedFollowRule is TokenGatedRule, IFollowRule { using AccessControlLib for IAccessControl; using AccessControlLib for address; - /// @custom:keccak lens.permission.SkipTokenGate - uint256 constant PID__SKIP_TOKEN_GATE = uint256(0x42073514d6ebc3c4c46bdc33d53105f5c563a0d184e86952704eb3e7b74ec1ae); + /// @custom:keccak lens.permission.SkipGate + uint256 constant PID__SKIP_GATE = uint256(0xeb7f30e4c97d5211e2534aa42375c26931bd55b57a8101e5eb7918daead714eb); /// @custom:keccak lens.param.accessControl bytes32 constant PARAM__ACCESS_CONTROL = 0xcf3b0fab90208e4185bf857e0f943f6672abffb7d0898e0750beeeb991ae35fa; @@ -27,7 +27,7 @@ contract TokenGatedFollowRule is TokenGatedRule, IFollowRule { mapping(address => mapping(address => mapping(bytes32 => Configuration))) internal _configuration; constructor(string memory metadataURI) TokenGatedRule(metadataURI) { - emit Events.Lens_PermissionId_Available(PID__SKIP_TOKEN_GATE, "lens.permission.SkipTokenGate"); + emit Events.Lens_PermissionId_Available(PID__SKIP_GATE, "lens.permission.SkipGate"); } function configure(bytes32 configSalt, address account, KeyValue[] calldata ruleParams) external override { @@ -57,7 +57,7 @@ contract TokenGatedFollowRule is TokenGatedRule, IFollowRule { TokenGateConfiguration memory tokenGateConfiguration, address account ) internal view { - if (!accessControl.hasAccess(account, PID__SKIP_TOKEN_GATE)) { + if (!accessControl.hasAccess(account, PID__SKIP_GATE)) { _validateTokenBalance(tokenGateConfiguration, account); } } diff --git a/contracts/rules/graph/GroupGatedGraphRule.sol b/contracts/rules/graph/GroupGatedGraphRule.sol index 6f990860..9dbd3abf 100644 --- a/contracts/rules/graph/GroupGatedGraphRule.sol +++ b/contracts/rules/graph/GroupGatedGraphRule.sol @@ -17,8 +17,8 @@ contract GroupGatedGraphRule is IGraphRule, MetadataBased { event Lens_Rule_MetadataURISet(string metadataURI); - /// @custom:keccak lens.permission.SkipTokenGate - uint256 constant PID__SKIP_TOKEN_GATE = uint256(0x42073514d6ebc3c4c46bdc33d53105f5c563a0d184e86952704eb3e7b74ec1ae); + /// @custom:keccak lens.permission.SkipGate + uint256 constant PID__SKIP_GATE = uint256(0xeb7f30e4c97d5211e2534aa42375c26931bd55b57a8101e5eb7918daead714eb); /// @custom:keccak lens.param.accessControl bytes32 constant PARAM__ACCESS_CONTROL = 0xcf3b0fab90208e4185bf857e0f943f6672abffb7d0898e0750beeeb991ae35fa; @@ -34,7 +34,7 @@ contract GroupGatedGraphRule is IGraphRule, MetadataBased { constructor(string memory metadataURI) { _setMetadataURI(metadataURI); - emit Events.Lens_PermissionId_Available(PID__SKIP_TOKEN_GATE, "lens.permission.SkipTokenGate"); + emit Events.Lens_PermissionId_Available(PID__SKIP_GATE, "lens.permission.SkipGate"); } function _emitMetadataURISet(string memory metadataURI) internal override { @@ -93,7 +93,7 @@ contract GroupGatedGraphRule is IGraphRule, MetadataBased { } function _validateGroupMembership(address accessControl, address group, address account) internal view { - if (!accessControl.hasAccess(account, PID__SKIP_TOKEN_GATE)) { + if (!accessControl.hasAccess(account, PID__SKIP_GATE)) { require(IGroup(group).isMember(account), Errors.NotAMember()); } } diff --git a/contracts/rules/graph/TokenGatedGraphRule.sol b/contracts/rules/graph/TokenGatedGraphRule.sol index b2e4ac5e..62db205e 100644 --- a/contracts/rules/graph/TokenGatedGraphRule.sol +++ b/contracts/rules/graph/TokenGatedGraphRule.sol @@ -14,8 +14,8 @@ contract TokenGatedGraphRule is TokenGatedRule, IGraphRule { using AccessControlLib for IAccessControl; using AccessControlLib for address; - /// @custom:keccak lens.permission.SkipTokenGate - uint256 constant PID__SKIP_TOKEN_GATE = uint256(0x42073514d6ebc3c4c46bdc33d53105f5c563a0d184e86952704eb3e7b74ec1ae); + /// @custom:keccak lens.permission.SkipGate + uint256 constant PID__SKIP_GATE = uint256(0xeb7f30e4c97d5211e2534aa42375c26931bd55b57a8101e5eb7918daead714eb); /// @custom:keccak lens.param.accessControl bytes32 constant PARAM__ACCESS_CONTROL = 0xcf3b0fab90208e4185bf857e0f943f6672abffb7d0898e0750beeeb991ae35fa; @@ -28,7 +28,7 @@ contract TokenGatedGraphRule is TokenGatedRule, IGraphRule { mapping(address => mapping(bytes32 => Configuration)) internal _configuration; constructor(string memory metadataURI) TokenGatedRule(metadataURI) { - emit Events.Lens_PermissionId_Available(PID__SKIP_TOKEN_GATE, "lens.permission.SkipTokenGate"); + emit Events.Lens_PermissionId_Available(PID__SKIP_GATE, "lens.permission.SkipGate"); } function configure(bytes32 configSalt, KeyValue[] calldata ruleParams) external { @@ -87,7 +87,7 @@ contract TokenGatedGraphRule is TokenGatedRule, IGraphRule { TokenGateConfiguration memory tokenGateConfiguration, address account ) internal view { - if (!accessControl.hasAccess(account, PID__SKIP_TOKEN_GATE)) { + if (!accessControl.hasAccess(account, PID__SKIP_GATE)) { _validateTokenBalance(tokenGateConfiguration, account); } } diff --git a/contracts/rules/group/TokenGatedGroupRule.sol b/contracts/rules/group/TokenGatedGroupRule.sol index 3a63e4eb..4368ccc1 100644 --- a/contracts/rules/group/TokenGatedGroupRule.sol +++ b/contracts/rules/group/TokenGatedGroupRule.sol @@ -14,8 +14,8 @@ contract TokenGatedGroupRule is TokenGatedRule, IGroupRule { using AccessControlLib for IAccessControl; using AccessControlLib for address; - /// @custom:keccak lens.permission.SkipTokenGate - uint256 constant PID__SKIP_TOKEN_GATE = uint256(0x42073514d6ebc3c4c46bdc33d53105f5c563a0d184e86952704eb3e7b74ec1ae); + /// @custom:keccak lens.permission.SkipGate + uint256 constant PID__SKIP_GATE = uint256(0xeb7f30e4c97d5211e2534aa42375c26931bd55b57a8101e5eb7918daead714eb); /// @custom:keccak lens.param.accessControl bytes32 constant PARAM__ACCESS_CONTROL = 0xcf3b0fab90208e4185bf857e0f943f6672abffb7d0898e0750beeeb991ae35fa; @@ -28,7 +28,7 @@ contract TokenGatedGroupRule is TokenGatedRule, IGroupRule { mapping(address => mapping(bytes32 => Configuration)) internal _configuration; constructor(string memory metadataURI) TokenGatedRule(metadataURI) { - emit Events.Lens_PermissionId_Available(PID__SKIP_TOKEN_GATE, "lens.permission.SkipTokenGate"); + emit Events.Lens_PermissionId_Available(PID__SKIP_GATE, "lens.permission.SkipGate"); } function configure(bytes32 configSalt, KeyValue[] calldata ruleParams) external { @@ -86,7 +86,7 @@ contract TokenGatedGroupRule is TokenGatedRule, IGroupRule { TokenGateConfiguration memory tokenGateConfiguration, address account ) internal view { - if (!accessControl.hasAccess(account, PID__SKIP_TOKEN_GATE)) { + if (!accessControl.hasAccess(account, PID__SKIP_GATE)) { _validateTokenBalance(tokenGateConfiguration, account); } } diff --git a/contracts/rules/namespace/TokenGatedNamespaceRule.sol b/contracts/rules/namespace/TokenGatedNamespaceRule.sol index 18347ee5..a5e0aa10 100644 --- a/contracts/rules/namespace/TokenGatedNamespaceRule.sol +++ b/contracts/rules/namespace/TokenGatedNamespaceRule.sol @@ -13,8 +13,8 @@ contract TokenGatedNamespaceRule is TokenGatedRule, INamespaceRule { using AccessControlLib for IAccessControl; using AccessControlLib for address; - /// @custom:keccak lens.permission.SkipTokenGate - uint256 constant PID__SKIP_TOKEN_GATE = uint256(0x42073514d6ebc3c4c46bdc33d53105f5c563a0d184e86952704eb3e7b74ec1ae); + /// @custom:keccak lens.permission.SkipGate + uint256 constant PID__SKIP_GATE = uint256(0xeb7f30e4c97d5211e2534aa42375c26931bd55b57a8101e5eb7918daead714eb); /// @custom:keccak lens.param.accessControl bytes32 constant PARAM__ACCESS_CONTROL = 0xcf3b0fab90208e4185bf857e0f943f6672abffb7d0898e0750beeeb991ae35fa; @@ -27,7 +27,7 @@ contract TokenGatedNamespaceRule is TokenGatedRule, INamespaceRule { mapping(address => mapping(bytes32 => Configuration)) internal _configuration; constructor(string memory metadataURI) TokenGatedRule(metadataURI) { - emit Events.Lens_PermissionId_Available(PID__SKIP_TOKEN_GATE, "lens.permission.SkipTokenGate"); + emit Events.Lens_PermissionId_Available(PID__SKIP_GATE, "lens.permission.SkipGate"); } function configure(bytes32 configSalt, KeyValue[] calldata ruleParams) external { @@ -101,7 +101,7 @@ contract TokenGatedNamespaceRule is TokenGatedRule, INamespaceRule { TokenGateConfiguration memory tokenGateConfiguration, address account ) internal view { - if (!accessControl.hasAccess(account, PID__SKIP_TOKEN_GATE)) { + if (!accessControl.hasAccess(account, PID__SKIP_GATE)) { _validateTokenBalance(tokenGateConfiguration, account); } } From dfd8e4b3882e453125b5e118da064fb8dc2ddbd4 Mon Sep 17 00:00:00 2001 From: Alan Donoso Naumczuk Date: Tue, 14 Jan 2025 16:20:14 -0300 Subject: [PATCH 22/41] fix: Added missing _processEntityRulesChanges override on Feed and Graph --- contracts/core/primitives/feed/RuleBasedFeed.sol | 12 ++++++++++-- contracts/core/primitives/graph/RuleBasedGraph.sol | 12 ++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/contracts/core/primitives/feed/RuleBasedFeed.sol b/contracts/core/primitives/feed/RuleBasedFeed.sol index 5b8ffa2a..ca0156ba 100644 --- a/contracts/core/primitives/feed/RuleBasedFeed.sol +++ b/contracts/core/primitives/feed/RuleBasedFeed.sol @@ -52,6 +52,14 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { _changeEntityRules($postRulesStorage(postId), postId, ruleChanges, ruleChangesProcessingParams); } + function _processEntityRulesChanges( + uint256 entityId, + RuleChange[] memory ruleChanges, + RuleProcessingParams[] memory ruleChangesProcessingParams + ) internal virtual override { + _processPostRulesChanges(entityId, ruleChanges, ruleChangesProcessingParams); + } + function _supportedPrimitiveRuleSelectors() internal view virtual override returns (bytes4[] memory) { bytes4[] memory selectors = new bytes4[](4); selectors[0] = IFeedRule.processCreatePost.selector; @@ -447,8 +455,8 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { function _processPostRulesChanges( uint256 postId, - RuleChange[] calldata ruleChanges, - RuleProcessingParams[] calldata rulesProcessingParams + RuleChange[] memory ruleChanges, + RuleProcessingParams[] memory rulesProcessingParams ) internal { bytes4 ruleSelector = IFeedRule.processPostRuleChanges.selector; // Check required rules (AND-combined rules) diff --git a/contracts/core/primitives/graph/RuleBasedGraph.sol b/contracts/core/primitives/graph/RuleBasedGraph.sol index 418877d1..015b07f4 100644 --- a/contracts/core/primitives/graph/RuleBasedGraph.sol +++ b/contracts/core/primitives/graph/RuleBasedGraph.sol @@ -53,6 +53,14 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive { ); } + function _processEntityRulesChanges( + uint256 entityId, + RuleChange[] memory ruleChanges, + RuleProcessingParams[] memory ruleChangesProcessingParams + ) internal virtual override { + _graphProcessFollowRuleChanges(address(uint160(entityId)), ruleChanges, ruleChangesProcessingParams); + } + function _supportedPrimitiveRuleSelectors() internal view virtual override returns (bytes4[] memory) { bytes4[] memory selectors = new bytes4[](3); selectors[0] = IGraphRule.processFollow.selector; @@ -132,8 +140,8 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive { function _graphProcessFollowRuleChanges( address account, - RuleChange[] calldata ruleChanges, - RuleProcessingParams[] calldata graphRulesProcessingParams + RuleChange[] memory ruleChanges, + RuleProcessingParams[] memory graphRulesProcessingParams ) internal { bytes4 ruleSelector = IGraphRule.processFollowRuleChanges.selector; // Check required rules (AND-combined rules) From a936313864a8ec5b13f4c61ac0b3af048da39426 Mon Sep 17 00:00:00 2001 From: Alan Donoso Naumczuk Date: Tue, 14 Jan 2025 16:20:31 -0300 Subject: [PATCH 23/41] misc: getUsernameTokenId modifier from view to pure --- contracts/core/primitives/namespace/Namespace.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/core/primitives/namespace/Namespace.sol b/contracts/core/primitives/namespace/Namespace.sol index 5c2e2395..0bffc812 100644 --- a/contracts/core/primitives/namespace/Namespace.sol +++ b/contracts/core/primitives/namespace/Namespace.sol @@ -311,7 +311,7 @@ contract Namespace is return _exists(tokenId); } - function getUsernameTokenId(string calldata username) external view returns (uint256) { + function getUsernameTokenId(string calldata username) external pure returns (uint256) { return _computeId(username); } } From df046e992aa115d7d569d480a5c087f902436436 Mon Sep 17 00:00:00 2001 From: vicnaum Date: Wed, 15 Jan 2025 12:44:59 +0100 Subject: [PATCH 24/41] misc: add TippingPostAction to deployment script --- deploy/deployActions.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/deploy/deployActions.ts b/deploy/deployActions.ts index 7cc35703..34b296c9 100644 --- a/deploy/deployActions.ts +++ b/deploy/deployActions.ts @@ -9,6 +9,7 @@ export async function deployActions(actionHub: string): Promise { const contracts: ContractInfo[] = [ // Actions { contractName: 'TippingAccountAction', contractType: ContractType.Action, constructorArguments: [actionHub, metadataURI] }, + { contractName: 'TippingPostAction', contractType: ContractType.Action, constructorArguments: [actionHub, metadataURI] }, { contractName: 'SimpleCollectAction', contractType: ContractType.Action, constructorArguments: [actionHub, metadataURI] }, ]; From fdbd1c7815d521a5ded2c7da89ea4b76a999702a Mon Sep 17 00:00:00 2001 From: vicnaum Date: Thu, 16 Jan 2025 11:27:01 +0100 Subject: [PATCH 25/41] fix: Post Rules events emitters added --- .../core/primitives/feed/RuleBasedFeed.sol | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/contracts/core/primitives/feed/RuleBasedFeed.sol b/contracts/core/primitives/feed/RuleBasedFeed.sol index ca0156ba..e12727d4 100644 --- a/contracts/core/primitives/feed/RuleBasedFeed.sol +++ b/contracts/core/primitives/feed/RuleBasedFeed.sol @@ -112,6 +112,39 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { } } + function _emitEntityRuleConfiguredEvent( + bool wasAlreadyConfigured, + uint256 entityId, + address ruleAddress, + bytes32 configSalt, + KeyValue[] memory ruleParams + ) internal override { + if (wasAlreadyConfigured) { + emit IFeed.Lens_Feed_Post_RuleReconfigured(entityId, msg.sender, ruleAddress, configSalt, ruleParams); + } else { + emit IFeed.Lens_Feed_Post_RuleConfigured(entityId, msg.sender, ruleAddress, configSalt, ruleParams); + } + } + + function _emitEntityRuleSelectorEvent( + bool enabled, + uint256 entityId, + address ruleAddress, + bytes32 configSalt, + bool isRequired, + bytes4 selector + ) internal override { + if (enabled) { + emit IFeed.Lens_Feed_Post_RuleSelectorEnabled( + entityId, msg.sender, ruleAddress, configSalt, isRequired, selector + ); + } else { + emit IFeed.Lens_Feed_Post_RuleSelectorDisabled( + entityId, msg.sender, ruleAddress, configSalt, isRequired, selector + ); + } + } + function _amountOfRules(bytes4 ruleSelector) internal view returns (uint256) { return $feedRulesStorage()._getRulesArray(ruleSelector, false).length + $feedRulesStorage()._getRulesArray(ruleSelector, true).length; From 1a5ce2a6423e60299b26e10258899ea0fdaa1928 Mon Sep 17 00:00:00 2001 From: vicnaum Date: Thu, 16 Jan 2025 11:32:50 +0100 Subject: [PATCH 26/41] fix: Follow Rules events emitters added --- .../core/primitives/graph/RuleBasedGraph.sol | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/contracts/core/primitives/graph/RuleBasedGraph.sol b/contracts/core/primitives/graph/RuleBasedGraph.sol index 015b07f4..827f5f12 100644 --- a/contracts/core/primitives/graph/RuleBasedGraph.sol +++ b/contracts/core/primitives/graph/RuleBasedGraph.sol @@ -111,6 +111,37 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive { } } + function _emitEntityRuleConfiguredEvent( + bool wasAlreadyConfigured, + uint256 entityId, + address ruleAddress, + bytes32 configSalt, + KeyValue[] memory ruleParams + ) internal override { + address account = address(uint160(entityId)); + if (wasAlreadyConfigured) { + emit IGraph.Lens_Graph_Follow_RuleReconfigured(account, ruleAddress, configSalt, ruleParams); + } else { + emit IGraph.Lens_Graph_Follow_RuleConfigured(account, ruleAddress, configSalt, ruleParams); + } + } + + function _emitEntityRuleSelectorEvent( + bool enabled, + uint256 entityId, + address ruleAddress, + bytes32 configSalt, + bool isRequired, + bytes4 selector + ) internal override { + address account = address(uint160(entityId)); + if (enabled) { + emit IGraph.Lens_Graph_Follow_RuleSelectorEnabled(account, ruleAddress, configSalt, isRequired, selector); + } else { + emit IGraph.Lens_Graph_Follow_RuleSelectorDisabled(account, ruleAddress, configSalt, isRequired, selector); + } + } + function _amountOfRules(bytes4 ruleSelector) internal view returns (uint256) { return $graphRulesStorage()._getRulesArray(ruleSelector, false).length + $graphRulesStorage()._getRulesArray(ruleSelector, true).length; From dd7919c5b061923001fef0d14e576a623d1a8f6c Mon Sep 17 00:00:00 2001 From: vicnaum Date: Thu, 16 Jan 2025 18:23:13 +0100 Subject: [PATCH 27/41] fix: editPost fixed (core call missing) --- contracts/core/primitives/feed/Feed.sol | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/contracts/core/primitives/feed/Feed.sol b/contracts/core/primitives/feed/Feed.sol index 8df76e91..64a2b1ca 100644 --- a/contracts/core/primitives/feed/Feed.sol +++ b/contracts/core/primitives/feed/Feed.sol @@ -133,17 +133,20 @@ contract Feed is function editPost( uint256 postId, - EditPostParams memory postParams, + EditPostParams calldata postParams, KeyValue[] memory customParams, RuleProcessingParams[] memory feedRulesParams, RuleProcessingParams[] memory rootPostRulesParams, RuleProcessingParams[] memory quotedPostRulesParams ) external virtual override { + require(Core._postExists(postId), Errors.DoesNotExist()); address author = Core.$storage().posts[postId].author; // TODO: We can have this for moderators: // require(msg.sender == author || _hasAccess(msg.sender, EDIT_POST_PID)); require(msg.sender == author, Errors.InvalidMsgSender()); + Core._editPost(postId, postParams); + bool[] memory wereExtraDataValuesSet = new bool[](postParams.extraData.length); for (uint256 i = 0; i < postParams.extraData.length; i++) { wereExtraDataValuesSet[i] = _setEntityExtraData(postId, postParams.extraData[i]); @@ -186,6 +189,7 @@ contract Feed is KeyValue[] calldata customParams, RuleProcessingParams[] calldata feedRulesParams ) external virtual override { + require(Core._postExists(postId), Errors.DoesNotExist()); address author = Core.$storage().posts[postId].author; require(msg.sender == author || _hasAccess(msg.sender, PID__REMOVE_POST), Errors.InvalidMsgSender()); Core._removePost(postId); From b862efd1f1caebf445950d2ce13ba24da0a72341 Mon Sep 17 00:00:00 2001 From: vicnaum Date: Thu, 16 Jan 2025 18:50:43 +0100 Subject: [PATCH 28/41] misc: MigrationFeed changed to have forceChecks always --- contracts/migration/MigrationFeed.sol | 82 ++++++++++----------------- 1 file changed, 30 insertions(+), 52 deletions(-) diff --git a/contracts/migration/MigrationFeed.sol b/contracts/migration/MigrationFeed.sol index 6bc8387a..76947932 100644 --- a/contracts/migration/MigrationFeed.sol +++ b/contracts/migration/MigrationFeed.sol @@ -9,9 +9,6 @@ import {Feed} from "contracts/core/primitives/feed/Feed.sol"; import {Errors} from "contracts/core/types/Errors.sol"; struct PostCreationParams { - uint256 postId; - uint256 rootPostId; - uint256 postSequentialId; uint256 authorPostSequentialId; uint80 creationTimestamp; address source; @@ -26,35 +23,24 @@ contract MigrationFeed is Feed { RuleProcessingParams[] memory quotedPostRulesParams ) external override returns (uint256) { PostCreationParams memory postCreationParams = abi.decode(customParams[0].value, (PostCreationParams)); - _createPost( - postParams, - postCreationParams.postId, - postCreationParams.rootPostId, - postCreationParams.postSequentialId, - postCreationParams.authorPostSequentialId, - postCreationParams.creationTimestamp - ); - - if (customParams.length > 1 && abi.decode(customParams[1].value, (bool))) { - // If customParams[1] is present, it must be an ABI-encoded bool representing `forceChecks` - _forceChecks(postCreationParams.postId, postCreationParams.rootPostId, postParams); - } + (uint256 postId, uint256 rootPostId) = + _createPost(postParams, postCreationParams.authorPostSequentialId, postCreationParams.creationTimestamp); if (postCreationParams.source != address(0)) { // Trust the migrator, no source verification _setPrimitiveInternalExtraDataForEntity( - postCreationParams.postId, KeyValue(DATA__SOURCE, abi.encode(postCreationParams.source)) + postId, KeyValue(DATA__SOURCE, abi.encode(postCreationParams.source)) ); _setPrimitiveInternalExtraDataForEntity( - postCreationParams.postId, KeyValue(DATA__LAST_UPDATED_SOURCE, abi.encode(postCreationParams.source)) + postId, KeyValue(DATA__LAST_UPDATED_SOURCE, abi.encode(postCreationParams.source)) ); } emit Lens_Feed_PostCreated( - postCreationParams.postId, + postId, postParams.author, postCreationParams.authorPostSequentialId, - postCreationParams.rootPostId, + rootPostId, postParams, customParams, feedRulesParams, @@ -64,64 +50,56 @@ contract MigrationFeed is Feed { ); for (uint256 i = 0; i < postParams.extraData.length; i++) { - _setExtraData(postParams.author, postCreationParams.postId, postParams.extraData[i]); + _setExtraData(postParams.author, postId, postParams.extraData[i]); emit Lens_Feed_Post_ExtraDataAdded( - postCreationParams.postId, - postParams.extraData[i].key, - postParams.extraData[i].value, - postParams.extraData[i].value + postId, postParams.extraData[i].key, postParams.extraData[i].value, postParams.extraData[i].value ); } - return postCreationParams.postId; + return postId; } // Overriding the FeedCore - function _createPost( - CreatePostParams memory postParams, - uint256 postId, - uint256 rootPostId, - uint256 postSequentialId, - uint256 authorPostSequentialId, - uint80 creationTimestamp - ) internal { - require(postParams.author != address(0), Errors.InvalidParameter()); - require(postId != 0, Errors.InvalidParameter()); - require(postSequentialId != 0, Errors.InvalidParameter()); + function _createPost(CreatePostParams memory postParams, uint256 authorPostSequentialId, uint80 creationTimestamp) + internal + returns (uint256, uint256) + { require(authorPostSequentialId != 0, Errors.InvalidParameter()); require(creationTimestamp != 0, Errors.InvalidParameter()); - Core.$storage().postCount++; + uint256 postSequentialId = Core.$storage().postCount++; Core.$storage().authorPostCount[postParams.author]++; + uint256 postId = Core._generatePostId(postParams.author, authorPostSequentialId); PostStorage storage _newPost = Core.$storage().posts[postId]; + _newPost.author = postParams.author; _newPost.authorPostSequentialId = authorPostSequentialId; _newPost.postSequentialId = postSequentialId; _newPost.contentURI = postParams.contentURI; - _newPost.quotedPostId = postParams.quotedPostId; - _newPost.repliedPostId = postParams.repliedPostId; - _newPost.repostedPostId = postParams.repostedPostId; - _newPost.rootPostId = rootPostId; - _newPost.creationTimestamp = creationTimestamp; - _newPost.lastUpdatedTimestamp = creationTimestamp; - } - function _forceChecks(uint256 postId, uint256 rootPostId, CreatePostParams memory postParams) internal view { - // TODO: Check if the rootPostId == postId case (not a reply, not a repost) - if (rootPostId != postId) { - require(Core._postExists(rootPostId), Errors.DoesNotExist()); - } + uint256 rootPostId = postId; + if (postParams.quotedPostId != 0) { require(Core._postExists(postParams.quotedPostId), Errors.DoesNotExist()); + _newPost.quotedPostId = postParams.quotedPostId; } if (postParams.repliedPostId != 0) { require(Core._postExists(postParams.repliedPostId), Errors.DoesNotExist()); - require(rootPostId == Core.$storage().posts[postParams.repliedPostId].rootPostId, Errors.InvalidParameter()); + _newPost.repliedPostId = postParams.repliedPostId; + rootPostId = Core.$storage().posts[postParams.repliedPostId].rootPostId; } if (postParams.repostedPostId != 0) { require(Core._postExists(postParams.repostedPostId), Errors.DoesNotExist()); + _newPost.repostedPostId = postParams.repostedPostId; + rootPostId = Core.$storage().posts[postParams.repostedPostId].rootPostId; require(postParams.quotedPostId == 0 && postParams.repliedPostId == 0, Errors.InvalidParameter()); - require(rootPostId == Core.$storage().posts[postParams.repostedPostId].rootPostId, Errors.InvalidParameter()); require(bytes(postParams.contentURI).length == 0, Errors.InvalidParameter()); } + if (rootPostId != postId) { + require(Core._postExists(rootPostId), Errors.DoesNotExist()); + } + _newPost.rootPostId = rootPostId; + _newPost.creationTimestamp = creationTimestamp; + _newPost.lastUpdatedTimestamp = creationTimestamp; + return (postId, rootPostId); } } From 404b46143aa3495e578d3cbc6000c0f2efd4442b Mon Sep 17 00:00:00 2001 From: Alan Donoso Naumczuk Date: Thu, 16 Jan 2025 15:47:47 -0300 Subject: [PATCH 29/41] fix: Rule processing main for-loop logic fixed - Call with empty params when processing params not present --- contracts/core/base/RuleBasedPrimitive.sol | 16 ++ .../core/primitives/feed/RuleBasedFeed.sol | 184 ++++++------------ .../core/primitives/graph/RuleBasedGraph.sol | 136 +++++-------- .../core/primitives/group/RuleBasedGroup.sol | 52 ++--- .../namespace/RuleBasedNamespace.sol | 52 ++--- 5 files changed, 159 insertions(+), 281 deletions(-) diff --git a/contracts/core/base/RuleBasedPrimitive.sol b/contracts/core/base/RuleBasedPrimitive.sol index e1acb778..f93ddf96 100644 --- a/contracts/core/base/RuleBasedPrimitive.sol +++ b/contracts/core/base/RuleBasedPrimitive.sol @@ -247,4 +247,20 @@ abstract contract RuleBasedPrimitive { ); return configSalt; } + + function _getRuleParamsOrEmptyArray(Rule memory rule, RuleProcessingParams[] memory rulesProcessingParams) + internal + pure + returns (KeyValue[] memory) + { + for (uint256 i = 0; i < rulesProcessingParams.length; i++) { + if ( + rulesProcessingParams[i].ruleAddress == rule.ruleAddress + && rulesProcessingParams[i].configSalt == rule.configSalt + ) { + return rulesProcessingParams[i].ruleParams; + } + } + return new KeyValue[](0); + } } diff --git a/contracts/core/primitives/feed/RuleBasedFeed.sol b/contracts/core/primitives/feed/RuleBasedFeed.sol index e12727d4..39fbc66b 100644 --- a/contracts/core/primitives/feed/RuleBasedFeed.sol +++ b/contracts/core/primitives/feed/RuleBasedFeed.sol @@ -179,7 +179,7 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { function _encodeAndCallProcessCreatePostOnFeed( Rule memory rule, ProcessPostCreationParams memory processParams, - KeyValue[] memory ruleCustomParams + KeyValue[] memory ruleParams ) internal returns (bool, bytes memory) { return rule.ruleAddress.safecall( abi.encodeCall( @@ -189,7 +189,7 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { processParams.postId, processParams.postParams, processParams.primitiveCustomParams, - ruleCustomParams + ruleParams ) ) ); @@ -198,7 +198,7 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { function _encodeAndCallProcessCreatePostOnRootPost( Rule memory rule, ProcessPostCreationParams memory processParams, - KeyValue[] memory ruleCustomParams + KeyValue[] memory ruleParams ) internal returns (bool, bytes memory) { return rule.ruleAddress.safecall( abi.encodeCall( @@ -209,7 +209,7 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { processParams.postId, processParams.postParams, processParams.primitiveCustomParams, - ruleCustomParams + ruleParams ) ) ); @@ -231,36 +231,22 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { ) internal { RulesStorage storage _rulesStorage = processParams.rootPostId == 0 ? $feedRulesStorage() : $postRulesStorage(processParams.rootPostId); + Rule memory rule; + KeyValue[] memory ruleParams; // Check required rules (AND-combined rules) for (uint256 i = 0; i < _rulesStorage.requiredRules[processParams.ruleSelector].length; i++) { - Rule memory rule = _rulesStorage.requiredRules[processParams.ruleSelector][i]; - for (uint256 j = 0; j < processParams.rulesProcessingParams.length; j++) { - KeyValue[] memory ruleCustomParams = new KeyValue[](0); - if ( - processParams.rulesProcessingParams[j].ruleAddress == rule.ruleAddress - && processParams.rulesProcessingParams[j].configSalt == rule.configSalt - ) { - ruleCustomParams = processParams.rulesProcessingParams[j].ruleParams; - } - (bool callNotReverted,) = encodeAndCall(rule, processParams, ruleCustomParams); - require(callNotReverted, Errors.RequiredRuleReverted()); - } + rule = _rulesStorage.requiredRules[processParams.ruleSelector][i]; + ruleParams = _getRuleParamsOrEmptyArray(rule, processParams.rulesProcessingParams); + (bool callSucceeded,) = encodeAndCall(rule, processParams, ruleParams); + require(callSucceeded, Errors.RequiredRuleReverted()); } // Check any-of rules (OR-combined rules) for (uint256 i = 0; i < _rulesStorage.anyOfRules[processParams.ruleSelector].length; i++) { - Rule memory rule = _rulesStorage.anyOfRules[processParams.ruleSelector][i]; - for (uint256 j = 0; j < processParams.rulesProcessingParams.length; j++) { - KeyValue[] memory ruleCustomParams = new KeyValue[](0); - if ( - processParams.rulesProcessingParams[j].ruleAddress == rule.ruleAddress - && processParams.rulesProcessingParams[j].configSalt == rule.configSalt - ) { - ruleCustomParams = processParams.rulesProcessingParams[j].ruleParams; - } - (bool callNotReverted,) = encodeAndCall(rule, processParams, ruleCustomParams); - if (callNotReverted) { - return; // If any of the OR-combined rules passed, it means they succeed and we can return - } + rule = _rulesStorage.anyOfRules[processParams.ruleSelector][i]; + ruleParams = _getRuleParamsOrEmptyArray(rule, processParams.rulesProcessingParams); + (bool callSucceeded,) = encodeAndCall(rule, processParams, ruleParams); + if (callSucceeded) { + return; // If any of the OR-combined rules passed, it means they succeed and we can return } } // If there are any-of rules and it reached this point, it means all of them failed. @@ -348,7 +334,7 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { function _encodeAndCallProcessEditPostOnFeed( Rule memory rule, ProcessPostEditingParams memory processParams, - KeyValue[] memory ruleCustomParams + KeyValue[] memory ruleParams ) internal returns (bool, bytes memory) { return rule.ruleAddress.safecall( abi.encodeCall( @@ -358,7 +344,7 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { processParams.postId, processParams.postParams, processParams.primitiveCustomParams, - ruleCustomParams + ruleParams ) ) ); @@ -367,7 +353,7 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { function _encodeAndCallProcessEditPostOnRootPost( Rule memory rule, ProcessPostEditingParams memory processParams, - KeyValue[] memory ruleCustomParams + KeyValue[] memory ruleParams ) internal returns (bool, bytes memory) { return rule.ruleAddress.safecall( abi.encodeCall( @@ -378,7 +364,7 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { processParams.postId, processParams.postParams, processParams.primitiveCustomParams, - ruleCustomParams + ruleParams ) ) ); @@ -400,36 +386,22 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { ) internal { RulesStorage storage _rulesStorage = processParams.rootPostId == 0 ? $feedRulesStorage() : $postRulesStorage(processParams.rootPostId); + Rule memory rule; + KeyValue[] memory ruleParams; // Check required rules (AND-combined rules) for (uint256 i = 0; i < _rulesStorage.requiredRules[processParams.ruleSelector].length; i++) { - Rule memory rule = _rulesStorage.requiredRules[processParams.ruleSelector][i]; - for (uint256 j = 0; j < processParams.rulesProcessingParams.length; j++) { - KeyValue[] memory ruleCustomParams = new KeyValue[](0); - if ( - processParams.rulesProcessingParams[j].ruleAddress == rule.ruleAddress - && processParams.rulesProcessingParams[j].configSalt == rule.configSalt - ) { - ruleCustomParams = processParams.rulesProcessingParams[j].ruleParams; - } - (bool callNotReverted,) = encodeAndCall(rule, processParams, ruleCustomParams); - require(callNotReverted, Errors.RequiredRuleReverted()); - } + rule = _rulesStorage.requiredRules[processParams.ruleSelector][i]; + ruleParams = _getRuleParamsOrEmptyArray(rule, processParams.rulesProcessingParams); + (bool callSucceeded,) = encodeAndCall(rule, processParams, ruleParams); + require(callSucceeded, Errors.RequiredRuleReverted()); } // Check any-of rules (OR-combined rules) for (uint256 i = 0; i < _rulesStorage.anyOfRules[processParams.ruleSelector].length; i++) { - Rule memory rule = _rulesStorage.anyOfRules[processParams.ruleSelector][i]; - for (uint256 j = 0; j < processParams.rulesProcessingParams.length; j++) { - KeyValue[] memory ruleCustomParams = new KeyValue[](0); - if ( - processParams.rulesProcessingParams[j].ruleAddress == rule.ruleAddress - && processParams.rulesProcessingParams[j].configSalt == rule.configSalt - ) { - ruleCustomParams = processParams.rulesProcessingParams[j].ruleParams; - } - (bool callNotReverted,) = encodeAndCall(rule, processParams, ruleCustomParams); - if (callNotReverted) { - return; // If any of the OR-combined rules passed, it means they succeed and we can return - } + rule = _rulesStorage.anyOfRules[processParams.ruleSelector][i]; + ruleParams = _getRuleParamsOrEmptyArray(rule, processParams.rulesProcessingParams); + (bool callSucceeded,) = encodeAndCall(rule, processParams, ruleParams); + if (callSucceeded) { + return; // If any of the OR-combined rules passed, it means they succeed and we can return } } // If there are any-of rules and it reached this point, it means all of them failed. @@ -442,44 +414,26 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { RuleProcessingParams[] calldata rulesProcessingParams ) internal { bytes4 ruleSelector = IFeedRule.processRemovePost.selector; + Rule memory rule; + KeyValue[] memory ruleParams; // Check required rules (AND-combined rules) for (uint256 i = 0; i < $feedRulesStorage().requiredRules[ruleSelector].length; i++) { - Rule memory rule = $feedRulesStorage().requiredRules[ruleSelector][i]; - for (uint256 j = 0; j < rulesProcessingParams.length; j++) { - KeyValue[] memory ruleCustomParams = new KeyValue[](0); - if ( - rulesProcessingParams[j].ruleAddress == rule.ruleAddress - && rulesProcessingParams[j].configSalt == rule.configSalt - ) { - ruleCustomParams = rulesProcessingParams[j].ruleParams; - } - (bool callNotReverted,) = rule.ruleAddress.safecall( - abi.encodeCall( - IFeedRule.processRemovePost, (rule.configSalt, postId, customParams, ruleCustomParams) - ) - ); - require(callNotReverted, Errors.RequiredRuleReverted()); - } + rule = $feedRulesStorage().requiredRules[ruleSelector][i]; + ruleParams = _getRuleParamsOrEmptyArray(rule, rulesProcessingParams); + (bool callSucceeded,) = rule.ruleAddress.safecall( + abi.encodeCall(IFeedRule.processRemovePost, (rule.configSalt, postId, customParams, ruleParams)) + ); + require(callSucceeded, Errors.RequiredRuleReverted()); } // Check any-of rules (OR-combined rules) for (uint256 i = 0; i < $feedRulesStorage().anyOfRules[ruleSelector].length; i++) { - Rule memory rule = $feedRulesStorage().anyOfRules[ruleSelector][i]; - for (uint256 j = 0; j < rulesProcessingParams.length; j++) { - KeyValue[] memory ruleCustomParams = new KeyValue[](0); - if ( - rulesProcessingParams[j].ruleAddress == rule.ruleAddress - && rulesProcessingParams[j].configSalt == rule.configSalt - ) { - ruleCustomParams = rulesProcessingParams[j].ruleParams; - } - (bool callNotReverted,) = rule.ruleAddress.safecall( - abi.encodeCall( - IFeedRule.processRemovePost, (rule.configSalt, postId, customParams, ruleCustomParams) - ) - ); - if (callNotReverted) { - return; // If any of the OR-combined rules passed, it means they succeed and we can return - } + rule = $feedRulesStorage().anyOfRules[ruleSelector][i]; + ruleParams = _getRuleParamsOrEmptyArray(rule, rulesProcessingParams); + (bool callSucceeded,) = rule.ruleAddress.safecall( + abi.encodeCall(IFeedRule.processRemovePost, (rule.configSalt, postId, customParams, ruleParams)) + ); + if (callSucceeded) { + return; // If any of the OR-combined rules passed, it means they succeed and we can return } } // If there are any-of rules and it reached this point, it means all of them failed. @@ -492,44 +446,26 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { RuleProcessingParams[] memory rulesProcessingParams ) internal { bytes4 ruleSelector = IFeedRule.processPostRuleChanges.selector; + Rule memory rule; + KeyValue[] memory ruleParams; // Check required rules (AND-combined rules) for (uint256 i = 0; i < $feedRulesStorage().requiredRules[ruleSelector].length; i++) { - Rule memory rule = $feedRulesStorage().requiredRules[ruleSelector][i]; - for (uint256 j = 0; j < rulesProcessingParams.length; j++) { - KeyValue[] memory ruleCustomParams = new KeyValue[](0); - if ( - rulesProcessingParams[j].ruleAddress == rule.ruleAddress - && rulesProcessingParams[j].configSalt == rule.configSalt - ) { - ruleCustomParams = rulesProcessingParams[j].ruleParams; - } - (bool callNotReverted,) = rule.ruleAddress.safecall( - abi.encodeCall( - IFeedRule.processPostRuleChanges, (rule.configSalt, postId, ruleChanges, ruleCustomParams) - ) - ); - require(callNotReverted, Errors.RequiredRuleReverted()); - } + rule = $feedRulesStorage().requiredRules[ruleSelector][i]; + ruleParams = _getRuleParamsOrEmptyArray(rule, rulesProcessingParams); + (bool callSucceeded,) = rule.ruleAddress.safecall( + abi.encodeCall(IFeedRule.processPostRuleChanges, (rule.configSalt, postId, ruleChanges, ruleParams)) + ); + require(callSucceeded, Errors.RequiredRuleReverted()); } // Check any-of rules (OR-combined rules) for (uint256 i = 0; i < $feedRulesStorage().anyOfRules[ruleSelector].length; i++) { - Rule memory rule = $feedRulesStorage().anyOfRules[ruleSelector][i]; - for (uint256 j = 0; j < rulesProcessingParams.length; j++) { - KeyValue[] memory ruleCustomParams = new KeyValue[](0); - if ( - rulesProcessingParams[j].ruleAddress == rule.ruleAddress - && rulesProcessingParams[j].configSalt == rule.configSalt - ) { - ruleCustomParams = rulesProcessingParams[j].ruleParams; - } - (bool callNotReverted,) = rule.ruleAddress.safecall( - abi.encodeCall( - IFeedRule.processPostRuleChanges, (rule.configSalt, postId, ruleChanges, ruleCustomParams) - ) - ); - if (callNotReverted) { - return; // If any of the OR-combined rules passed, it means they succeed and we can return - } + rule = $feedRulesStorage().anyOfRules[ruleSelector][i]; + ruleParams = _getRuleParamsOrEmptyArray(rule, rulesProcessingParams); + (bool callSucceeded,) = rule.ruleAddress.safecall( + abi.encodeCall(IFeedRule.processPostRuleChanges, (rule.configSalt, postId, ruleChanges, ruleParams)) + ); + if (callSucceeded) { + return; // If any of the OR-combined rules passed, it means they succeed and we can return } } // If there are any-of rules and it reached this point, it means all of them failed. diff --git a/contracts/core/primitives/graph/RuleBasedGraph.sol b/contracts/core/primitives/graph/RuleBasedGraph.sol index 827f5f12..da76c217 100644 --- a/contracts/core/primitives/graph/RuleBasedGraph.sol +++ b/contracts/core/primitives/graph/RuleBasedGraph.sol @@ -175,44 +175,26 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive { RuleProcessingParams[] memory graphRulesProcessingParams ) internal { bytes4 ruleSelector = IGraphRule.processFollowRuleChanges.selector; + Rule memory rule; + KeyValue[] memory ruleParams; // Check required rules (AND-combined rules) for (uint256 i = 0; i < $graphRulesStorage().requiredRules[ruleSelector].length; i++) { - Rule memory rule = $graphRulesStorage().requiredRules[ruleSelector][i]; - for (uint256 j = 0; j < graphRulesProcessingParams.length; j++) { - KeyValue[] memory ruleCustomParams = new KeyValue[](0); - if ( - graphRulesProcessingParams[j].ruleAddress == rule.ruleAddress - && graphRulesProcessingParams[j].configSalt == rule.configSalt - ) { - ruleCustomParams = graphRulesProcessingParams[j].ruleParams; - } - (bool callNotReverted,) = rule.ruleAddress.safecall( - abi.encodeCall( - IGraphRule.processFollowRuleChanges, (rule.configSalt, account, ruleChanges, ruleCustomParams) - ) - ); - require(callNotReverted, Errors.RequiredRuleReverted()); - } + rule = $graphRulesStorage().requiredRules[ruleSelector][i]; + ruleParams = _getRuleParamsOrEmptyArray(rule, graphRulesProcessingParams); + (bool callSucceeded,) = rule.ruleAddress.safecall( + abi.encodeCall(IGraphRule.processFollowRuleChanges, (rule.configSalt, account, ruleChanges, ruleParams)) + ); + require(callSucceeded, Errors.RequiredRuleReverted()); } // Check any-of rules (OR-combined rules) for (uint256 i = 0; i < $graphRulesStorage().anyOfRules[ruleSelector].length; i++) { - Rule memory rule = $graphRulesStorage().anyOfRules[ruleSelector][i]; - for (uint256 j = 0; j < graphRulesProcessingParams.length; j++) { - KeyValue[] memory ruleCustomParams = new KeyValue[](0); - if ( - graphRulesProcessingParams[j].ruleAddress == rule.ruleAddress - && graphRulesProcessingParams[j].configSalt == rule.configSalt - ) { - ruleCustomParams = graphRulesProcessingParams[j].ruleParams; - } - (bool callNotReverted,) = rule.ruleAddress.safecall( - abi.encodeCall( - IGraphRule.processFollowRuleChanges, (rule.configSalt, account, ruleChanges, ruleCustomParams) - ) - ); - if (callNotReverted) { - return; // If any of the OR-combined rules passed, it means they succeed and we can return - } + rule = $graphRulesStorage().anyOfRules[ruleSelector][i]; + ruleParams = _getRuleParamsOrEmptyArray(rule, graphRulesProcessingParams); + (bool callSucceeded,) = rule.ruleAddress.safecall( + abi.encodeCall(IGraphRule.processFollowRuleChanges, (rule.configSalt, account, ruleChanges, ruleParams)) + ); + if (callSucceeded) { + return; // If any of the OR-combined rules passed, it means they succeed and we can return } } // If there are any-of rules and it reached this point, it means all of them failed. @@ -230,7 +212,7 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive { function _encodeAndCallGraphProcessFollow( Rule memory rule, ProcessParams memory processParams, - KeyValue[] memory ruleCustomParams + KeyValue[] memory ruleParams ) internal returns (bool, bytes memory) { return rule.ruleAddress.safecall( abi.encodeCall( @@ -241,7 +223,7 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive { processParams.sourceAccount, processParams.targetAccount, processParams.primitiveCustomParams, - ruleCustomParams + ruleParams ) ) ); @@ -271,7 +253,7 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive { function _encodeAndCallGraphProcessUnfollow( Rule memory rule, ProcessParams memory processParams, - KeyValue[] memory ruleCustomParams + KeyValue[] memory ruleParams ) internal returns (bool, bytes memory) { return rule.ruleAddress.safecall( abi.encodeCall( @@ -282,7 +264,7 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive { processParams.sourceAccount, processParams.targetAccount, processParams.primitiveCustomParams, - ruleCustomParams + ruleParams ) ) ); @@ -311,7 +293,7 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive { function _encodeAndCallAccountProcessFollow( Rule memory rule, ProcessParams memory processParams, - KeyValue[] memory ruleCustomParams + KeyValue[] memory ruleParams ) internal returns (bool, bytes memory) { return rule.ruleAddress.safecall( abi.encodeCall( @@ -322,7 +304,7 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive { processParams.sourceAccount, processParams.targetAccount, processParams.primitiveCustomParams, - ruleCustomParams + ruleParams ) ) ); @@ -355,36 +337,22 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive { ProcessParams memory processParams ) internal { bytes4 ruleSelector = IGraphRule.processUnfollow.selector; + Rule memory rule; + KeyValue[] memory ruleParams; // Check required rules (AND-combined rules) for (uint256 i = 0; i < rulesStorage.requiredRules[ruleSelector].length; i++) { - Rule memory rule = rulesStorage.requiredRules[ruleSelector][i]; - // TODO: Think how to put this loop into a library (all the rules use it) - for (uint256 j = 0; j < processParams.rulesProcessingParams.length; j++) { - KeyValue[] memory ruleCustomParams = new KeyValue[](0); - if ( - processParams.rulesProcessingParams[j].ruleAddress == rule.ruleAddress - && processParams.rulesProcessingParams[j].configSalt == rule.configSalt - ) { - ruleCustomParams = processParams.rulesProcessingParams[j].ruleParams; - } - (bool callNotReverted,) = encodeAndCall(rule, processParams, ruleCustomParams); - require(callNotReverted, Errors.RequiredRuleReverted()); - } + rule = rulesStorage.requiredRules[ruleSelector][i]; + ruleParams = _getRuleParamsOrEmptyArray(rule, processParams.rulesProcessingParams); + (bool callSucceeded,) = encodeAndCall(rule, processParams, ruleParams); + require(callSucceeded, Errors.RequiredRuleReverted()); } + // Check any-of rules (OR-combined rules) for (uint256 i = 0; i < rulesStorage.anyOfRules[ruleSelector].length; i++) { - Rule memory rule = rulesStorage.anyOfRules[ruleSelector][i]; - for (uint256 j = 0; j < processParams.rulesProcessingParams.length; j++) { - KeyValue[] memory ruleCustomParams = new KeyValue[](0); - if ( - processParams.rulesProcessingParams[j].ruleAddress == rule.ruleAddress - && processParams.rulesProcessingParams[j].configSalt == rule.configSalt - ) { - ruleCustomParams = processParams.rulesProcessingParams[j].ruleParams; - } - (bool callNotReverted,) = encodeAndCall(rule, processParams, ruleCustomParams); - if (callNotReverted) { - return; // If any of the OR-combined rules passed, it means they succeed and we can return - } + rule = rulesStorage.anyOfRules[ruleSelector][i]; + ruleParams = _getRuleParamsOrEmptyArray(rule, processParams.rulesProcessingParams); + (bool callSucceeded,) = encodeAndCall(rule, processParams, ruleParams); + if (callSucceeded) { + return; // If any of the OR-combined rules passed, it means they succeed and we can return } } // If there are any-of rules and it reached this point, it means all of them failed. @@ -397,36 +365,22 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive { bytes4 ruleSelector, ProcessParams memory processParams ) internal { + Rule memory rule; + KeyValue[] memory ruleParams; // Check required rules (AND-combined rules) for (uint256 i = 0; i < rulesStorage.requiredRules[ruleSelector].length; i++) { - Rule memory rule = rulesStorage.requiredRules[ruleSelector][i]; - // TODO: Think how to put this loop into a library (all the rules use it) - for (uint256 j = 0; j < processParams.rulesProcessingParams.length; j++) { - KeyValue[] memory ruleCustomParams = new KeyValue[](0); - if ( - processParams.rulesProcessingParams[j].ruleAddress == rule.ruleAddress - && processParams.rulesProcessingParams[j].configSalt == rule.configSalt - ) { - ruleCustomParams = processParams.rulesProcessingParams[j].ruleParams; - } - (bool callNotReverted,) = encodeAndCall(rule, processParams, ruleCustomParams); - require(callNotReverted, Errors.RequiredRuleReverted()); - } + rule = rulesStorage.requiredRules[ruleSelector][i]; + ruleParams = _getRuleParamsOrEmptyArray(rule, processParams.rulesProcessingParams); + (bool callSucceeded,) = encodeAndCall(rule, processParams, ruleParams); + require(callSucceeded, Errors.RequiredRuleReverted()); } + // Check any-of rules (OR-combined rules) for (uint256 i = 0; i < rulesStorage.anyOfRules[ruleSelector].length; i++) { - Rule memory rule = rulesStorage.anyOfRules[ruleSelector][i]; - for (uint256 j = 0; j < processParams.rulesProcessingParams.length; j++) { - KeyValue[] memory ruleCustomParams = new KeyValue[](0); - if ( - processParams.rulesProcessingParams[j].ruleAddress == rule.ruleAddress - && processParams.rulesProcessingParams[j].configSalt == rule.configSalt - ) { - ruleCustomParams = processParams.rulesProcessingParams[j].ruleParams; - } - (bool callNotReverted,) = encodeAndCall(rule, processParams, ruleCustomParams); - if (callNotReverted) { - return; // If any of the OR-combined rules passed, it means they succeed and we can return - } + rule = rulesStorage.anyOfRules[ruleSelector][i]; + ruleParams = _getRuleParamsOrEmptyArray(rule, processParams.rulesProcessingParams); + (bool callSucceeded,) = encodeAndCall(rule, processParams, ruleParams); + if (callSucceeded) { + return; // If any of the OR-combined rules passed, it means they succeed and we can return } } // If there are any-of rules and it reached this point, it means all of them failed. diff --git a/contracts/core/primitives/group/RuleBasedGroup.sol b/contracts/core/primitives/group/RuleBasedGroup.sol index ce7edf0c..4ff96ca1 100644 --- a/contracts/core/primitives/group/RuleBasedGroup.sol +++ b/contracts/core/primitives/group/RuleBasedGroup.sol @@ -102,7 +102,7 @@ abstract contract RuleBasedGroup is IGroup, RuleBasedPrimitive { function _encodeAndCallProcessMemberRemoval( Rule memory rule, ProcessParams memory processParams, - KeyValue[] memory ruleCustomParams + KeyValue[] memory ruleParams ) internal returns (bool, bytes memory) { return rule.ruleAddress.safecall( abi.encodeCall( @@ -112,7 +112,7 @@ abstract contract RuleBasedGroup is IGroup, RuleBasedPrimitive { processParams.originalMsgSender, processParams.account, processParams.primitiveCustomParams, - ruleCustomParams + ruleParams ) ) ); @@ -139,7 +139,7 @@ abstract contract RuleBasedGroup is IGroup, RuleBasedPrimitive { function _encodeAndCallProcessMemberAddition( Rule memory rule, ProcessParams memory processParams, - KeyValue[] memory ruleCustomParams + KeyValue[] memory ruleParams ) internal returns (bool, bytes memory) { return rule.ruleAddress.safecall( abi.encodeCall( @@ -149,7 +149,7 @@ abstract contract RuleBasedGroup is IGroup, RuleBasedPrimitive { processParams.originalMsgSender, processParams.account, processParams.primitiveCustomParams, - ruleCustomParams + ruleParams ) ) ); @@ -176,12 +176,12 @@ abstract contract RuleBasedGroup is IGroup, RuleBasedPrimitive { function _encodeAndCallProcessMemberJoining( Rule memory rule, ProcessParams memory processParams, - KeyValue[] memory ruleCustomParams + KeyValue[] memory ruleParams ) internal returns (bool, bytes memory) { return rule.ruleAddress.safecall( abi.encodeCall( IGroupRule.processJoining, - (rule.configSalt, processParams.account, processParams.primitiveCustomParams, ruleCustomParams) + (rule.configSalt, processParams.account, processParams.primitiveCustomParams, ruleParams) ) ); } @@ -207,12 +207,12 @@ abstract contract RuleBasedGroup is IGroup, RuleBasedPrimitive { function _encodeAndCallProcessMemberLeaving( Rule memory rule, ProcessParams memory processParams, - KeyValue[] memory ruleCustomParams + KeyValue[] memory ruleParams ) internal returns (bool, bytes memory) { return rule.ruleAddress.safecall( abi.encodeCall( IGroupRule.processLeaving, - (rule.configSalt, processParams.account, processParams.primitiveCustomParams, ruleCustomParams) + (rule.configSalt, processParams.account, processParams.primitiveCustomParams, ruleParams) ) ); } @@ -247,36 +247,22 @@ abstract contract RuleBasedGroup is IGroup, RuleBasedPrimitive { function(Rule memory,ProcessParams memory,KeyValue[] memory) internal returns (bool,bytes memory) encodeAndCall, ProcessParams memory processParams ) private { + Rule memory rule; + KeyValue[] memory ruleParams; // Check required rules (AND-combined rules) for (uint256 i = 0; i < $groupRulesStorage().requiredRules[processParams.ruleSelector].length; i++) { - Rule memory rule = $groupRulesStorage().requiredRules[processParams.ruleSelector][i]; - for (uint256 j = 0; j < processParams.rulesProcessingParams.length; j++) { - KeyValue[] memory ruleParams = new KeyValue[](0); - if ( - processParams.rulesProcessingParams[j].ruleAddress == rule.ruleAddress - && processParams.rulesProcessingParams[j].configSalt == rule.configSalt - ) { - ruleParams = processParams.rulesProcessingParams[j].ruleParams; - } - (bool callNotReverted,) = encodeAndCall(rule, processParams, ruleParams); - require(callNotReverted, Errors.RequiredRuleReverted()); - } + rule = $groupRulesStorage().requiredRules[processParams.ruleSelector][i]; + ruleParams = _getRuleParamsOrEmptyArray(rule, processParams.rulesProcessingParams); + (bool callSucceeded,) = encodeAndCall(rule, processParams, ruleParams); + require(callSucceeded, Errors.RequiredRuleReverted()); } // Check any-of rules (OR-combined rules) for (uint256 i = 0; i < $groupRulesStorage().anyOfRules[processParams.ruleSelector].length; i++) { - Rule memory rule = $groupRulesStorage().anyOfRules[processParams.ruleSelector][i]; - for (uint256 j = 0; j < processParams.rulesProcessingParams.length; j++) { - KeyValue[] memory ruleParams = new KeyValue[](0); - if ( - processParams.rulesProcessingParams[j].ruleAddress == rule.ruleAddress - && processParams.rulesProcessingParams[j].configSalt == rule.configSalt - ) { - ruleParams = processParams.rulesProcessingParams[j].ruleParams; - } - (bool callNotReverted,) = encodeAndCall(rule, processParams, ruleParams); - if (callNotReverted) { - return; // If any of the OR-combined rules passed, it means they succeed and we can return - } + rule = $groupRulesStorage().anyOfRules[processParams.ruleSelector][i]; + ruleParams = _getRuleParamsOrEmptyArray(rule, processParams.rulesProcessingParams); + (bool callSucceeded,) = encodeAndCall(rule, processParams, ruleParams); + if (callSucceeded) { + return; // If any of the OR-combined rules passed, it means they succeed and we can return } } // If there are any-of rules and it reached this point, it means all of them failed. diff --git a/contracts/core/primitives/namespace/RuleBasedNamespace.sol b/contracts/core/primitives/namespace/RuleBasedNamespace.sol index b1356b89..7fabc7d8 100644 --- a/contracts/core/primitives/namespace/RuleBasedNamespace.sol +++ b/contracts/core/primitives/namespace/RuleBasedNamespace.sol @@ -102,7 +102,7 @@ abstract contract RuleBasedNamespace is INamespace, RuleBasedPrimitive { function _encodeAndCallProcessCreation( Rule memory rule, ProcessParams memory processParams, - KeyValue[] memory ruleCustomParams + KeyValue[] memory ruleParams ) internal returns (bool, bytes memory) { return rule.ruleAddress.safecall( abi.encodeCall( @@ -113,7 +113,7 @@ abstract contract RuleBasedNamespace is INamespace, RuleBasedPrimitive { processParams.account, processParams.username, processParams.primitiveCustomParams, - ruleCustomParams + ruleParams ) ) ); @@ -142,7 +142,7 @@ abstract contract RuleBasedNamespace is INamespace, RuleBasedPrimitive { function _encodeAndCallProcessRemoval( Rule memory rule, ProcessParams memory processParams, - KeyValue[] memory ruleCustomParams + KeyValue[] memory ruleParams ) internal returns (bool, bytes memory) { return rule.ruleAddress.safecall( abi.encodeCall( @@ -152,7 +152,7 @@ abstract contract RuleBasedNamespace is INamespace, RuleBasedPrimitive { processParams.originalMsgSender, processParams.username, processParams.primitiveCustomParams, - ruleCustomParams + ruleParams ) ) ); @@ -180,7 +180,7 @@ abstract contract RuleBasedNamespace is INamespace, RuleBasedPrimitive { function _encodeAndCallProcessAssigning( Rule memory rule, ProcessParams memory processParams, - KeyValue[] memory ruleCustomParams + KeyValue[] memory ruleParams ) internal returns (bool, bytes memory) { return rule.ruleAddress.safecall( abi.encodeCall( @@ -191,7 +191,7 @@ abstract contract RuleBasedNamespace is INamespace, RuleBasedPrimitive { processParams.account, processParams.username, processParams.primitiveCustomParams, - ruleCustomParams + ruleParams ) ) ); @@ -220,7 +220,7 @@ abstract contract RuleBasedNamespace is INamespace, RuleBasedPrimitive { function _encodeAndCallProcessUnassigning( Rule memory rule, ProcessParams memory processParams, - KeyValue[] memory ruleCustomParams + KeyValue[] memory ruleParams ) internal returns (bool, bytes memory) { return rule.ruleAddress.safecall( abi.encodeCall( @@ -231,7 +231,7 @@ abstract contract RuleBasedNamespace is INamespace, RuleBasedPrimitive { processParams.account, processParams.username, processParams.primitiveCustomParams, - ruleCustomParams + ruleParams ) ) ); @@ -270,36 +270,22 @@ abstract contract RuleBasedNamespace is INamespace, RuleBasedPrimitive { function(Rule memory,ProcessParams memory,KeyValue[] memory) internal returns (bool,bytes memory) encodeAndCall, ProcessParams memory processParams ) private { + Rule memory rule; + KeyValue[] memory ruleParams; // Check required rules (AND-combined rules) for (uint256 i = 0; i < $namespaceRulesStorage().requiredRules[processParams.ruleSelector].length; i++) { - Rule memory rule = $namespaceRulesStorage().requiredRules[processParams.ruleSelector][i]; - for (uint256 j = 0; j < processParams.rulesProcessingParams.length; j++) { - KeyValue[] memory ruleParams = new KeyValue[](0); - if ( - processParams.rulesProcessingParams[j].ruleAddress == rule.ruleAddress - && processParams.rulesProcessingParams[j].configSalt == rule.configSalt - ) { - ruleParams = processParams.rulesProcessingParams[j].ruleParams; - } - (bool callNotReverted,) = encodeAndCall(rule, processParams, ruleParams); - require(callNotReverted, Errors.RequiredRuleReverted()); - } + rule = $namespaceRulesStorage().requiredRules[processParams.ruleSelector][i]; + ruleParams = _getRuleParamsOrEmptyArray(rule, processParams.rulesProcessingParams); + (bool callSucceeded,) = encodeAndCall(rule, processParams, ruleParams); + require(callSucceeded, Errors.RequiredRuleReverted()); } // Check any-of rules (OR-combined rules) for (uint256 i = 0; i < $namespaceRulesStorage().anyOfRules[processParams.ruleSelector].length; i++) { - Rule memory rule = $namespaceRulesStorage().anyOfRules[processParams.ruleSelector][i]; - for (uint256 j = 0; j < processParams.rulesProcessingParams.length; j++) { - KeyValue[] memory ruleParams = new KeyValue[](0); - if ( - processParams.rulesProcessingParams[j].ruleAddress == rule.ruleAddress - && processParams.rulesProcessingParams[j].configSalt == rule.configSalt - ) { - ruleParams = processParams.rulesProcessingParams[j].ruleParams; - } - (bool callNotReverted,) = encodeAndCall(rule, processParams, ruleParams); - if (callNotReverted) { - return; // If any of the OR-combined rules passed, it means they succeed and we can return - } + rule = $namespaceRulesStorage().anyOfRules[processParams.ruleSelector][i]; + ruleParams = _getRuleParamsOrEmptyArray(rule, processParams.rulesProcessingParams); + (bool callSucceeded,) = encodeAndCall(rule, processParams, ruleParams); + if (callSucceeded) { + return; // If any of the OR-combined rules passed, it means they succeed and we can return } } // If there are any-of rules and it reached this point, it means all of them failed. From 39840824504a999d446beafcecfa1cfdeb64af58 Mon Sep 17 00:00:00 2001 From: Alan Donoso Naumczuk Date: Thu, 16 Jan 2025 15:48:45 -0300 Subject: [PATCH 30/41] misc: bool return from call renamed to callSucceeded for better code semantics --- contracts/core/libraries/CallLib.sol | 12 ++++++------ contracts/core/libraries/RulesLib.sol | 4 ++-- contracts/core/upgradeability/ProxyAdmin.sol | 4 ++-- contracts/extensions/account/Account.sol | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/contracts/core/libraries/CallLib.sol b/contracts/core/libraries/CallLib.sol index a808cb8b..8351ae2f 100644 --- a/contracts/core/libraries/CallLib.sol +++ b/contracts/core/libraries/CallLib.sol @@ -6,18 +6,18 @@ import {Errors} from "contracts/core/types/Errors.sol"; library CallLib { function safecall(address target, bytes memory data) internal returns (bool, bytes memory) { - (bool success, bytes memory returnData) = target.call(data); - if (success) { + (bool callSucceeded, bytes memory returnData) = target.call(data); + if (callSucceeded) { require(returnData.length != 0 || target.code.length != 0, Errors.NotAContract()); } - return (success, returnData); + return (callSucceeded, returnData); } function safecall(address target, uint256 value, bytes memory data) internal returns (bool, bytes memory) { - (bool success, bytes memory returnData) = target.call{value: value}(data); - if (success) { + (bool callSucceeded, bytes memory returnData) = target.call{value: value}(data); + if (callSucceeded) { require(returnData.length != 0 || target.code.length != 0, Errors.NotAContract()); } - return (success, returnData); + return (callSucceeded, returnData); } } diff --git a/contracts/core/libraries/RulesLib.sol b/contracts/core/libraries/RulesLib.sol index 389b5ae7..8774eaf0 100644 --- a/contracts/core/libraries/RulesLib.sol +++ b/contracts/core/libraries/RulesLib.sol @@ -46,8 +46,8 @@ library RulesLib { ) internal returns (bool) { bool wasAlreadyConfigured = rulesStorage.isConfigured[ruleAddress][configSalt]; rulesStorage.isConfigured[ruleAddress][configSalt] = true; - (bool success,) = ruleAddress.safecall(encodedConfigureCall); - require(success, Errors.ConfigureCallReverted()); + (bool callSucceeded,) = ruleAddress.safecall(encodedConfigureCall); + require(callSucceeded, Errors.ConfigureCallReverted()); return wasAlreadyConfigured; } diff --git a/contracts/core/upgradeability/ProxyAdmin.sol b/contracts/core/upgradeability/ProxyAdmin.sol index 56a038b3..fe0e3f65 100644 --- a/contracts/core/upgradeability/ProxyAdmin.sol +++ b/contracts/core/upgradeability/ProxyAdmin.sol @@ -38,8 +38,8 @@ contract ProxyAdmin is Ownable { require(selector != BeaconProxy.optInToAutoUpgrade.selector, Errors.Locked()); } // Do the call - (bool success, bytes memory ret) = to.safecall(value, data); - if (!success) { + (bool callSucceeded, bytes memory ret) = to.safecall(value, data); + if (!callSucceeded) { assembly { // Equivalent to reverting with the returned error selector if the length is not zero. let length := mload(ret) diff --git a/contracts/extensions/account/Account.sol b/contracts/extensions/account/Account.sol index 0c1bcff8..1acbcdaa 100644 --- a/contracts/extensions/account/Account.sol +++ b/contracts/extensions/account/Account.sol @@ -156,8 +156,8 @@ contract Account is IAccount, Initializable, Ownable, IERC721Receiver, ExtraStor require($storage().accountManagerPermissions[msg.sender].canTransferTokens, Errors.NotAllowed()); } } - (bool success, bytes memory ret) = to.call{value: value}(data); - if (!success) { + (bool callSucceeded, bytes memory ret) = to.call{value: value}(data); + if (!callSucceeded) { assembly { // Equivalent to reverting with the returned error selector if the length is not zero. let length := mload(ret) From 036baf814ce3c808aedf6bbeca5232fbb30956e3 Mon Sep 17 00:00:00 2001 From: Alan Donoso Naumczuk Date: Thu, 16 Jan 2025 18:20:14 -0300 Subject: [PATCH 31/41] misc: IAccessControl incomplete natspec comment completed --- contracts/core/interfaces/IAccessControl.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/core/interfaces/IAccessControl.sol b/contracts/core/interfaces/IAccessControl.sol index 54bd1564..6c11727e 100644 --- a/contracts/core/interfaces/IAccessControl.sol +++ b/contracts/core/interfaces/IAccessControl.sol @@ -12,7 +12,7 @@ interface IAccessControl { * Returns true if the account is allowed to change the access control in the given contract address, false if not. * * @param account The account to check if is allowed to change the access control. - * @param contractAddress The address where the access control . + * @param contractAddress The address where the access control is being changed. */ function canChangeAccessControl(address account, address contractAddress) external view returns (bool); From a7dce244e7785b7ecb72515bc31878221d027e5f Mon Sep 17 00:00:00 2001 From: Alan Donoso Naumczuk Date: Thu, 16 Jan 2025 18:21:22 -0300 Subject: [PATCH 32/41] fix: Access Control verification function now calls with address(this) and 1 instad of address(0) and 0, to avoid reverting with invalid param --- contracts/core/libraries/AccessControlLib.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/core/libraries/AccessControlLib.sol b/contracts/core/libraries/AccessControlLib.sol index 08d9d7ec..8a054b22 100644 --- a/contracts/core/libraries/AccessControlLib.sol +++ b/contracts/core/libraries/AccessControlLib.sol @@ -34,7 +34,7 @@ library AccessControlLib { } function verifyHasAccessFunction(IAccessControl accessControl) internal view { - accessControl.hasAccess(address(0), address(0), 0); // We expect this to not panic. + accessControl.hasAccess(address(this), address(this), 1); // We expect this to not panic. } function requireCanChangeAccessControl(address accessControl, address account) internal view { From 3ce2ff12e23dcf771bdfc9daedd946bd8afac4dc Mon Sep 17 00:00:00 2001 From: Alan Donoso Naumczuk Date: Thu, 16 Jan 2025 18:21:58 -0300 Subject: [PATCH 33/41] misc: Diff error constants and validations moved up on RoleBasedAccessControl --- contracts/core/access/RoleBasedAccessControl.sol | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/contracts/core/access/RoleBasedAccessControl.sol b/contracts/core/access/RoleBasedAccessControl.sol index b99b1eec..85b84214 100644 --- a/contracts/core/access/RoleBasedAccessControl.sol +++ b/contracts/core/access/RoleBasedAccessControl.sol @@ -100,7 +100,7 @@ contract RoleBasedAccessControl is IRoleBasedAccessControl { function _revokeRole(address account, uint256 roleId) internal virtual { uint256 accountRolesLength = _roles[account].length; - require(accountRolesLength > 0, Errors.InvalidParameter()); + require(accountRolesLength > 0, Errors.RedundantStateChange()); uint256 roleIndex = 0; while (roleIndex < accountRolesLength) { if (_roles[account][roleIndex] == roleId) { @@ -109,7 +109,7 @@ contract RoleBasedAccessControl is IRoleBasedAccessControl { roleIndex++; } } - require(roleIndex < accountRolesLength, Errors.NotFound()); // Index must be found before reaching the end of the array + require(roleIndex < accountRolesLength, Errors.RedundantStateChange()); // Index must be found before reaching the end of the array _roles[account][roleIndex] = _roles[account][accountRolesLength - 1]; _roles[account].pop(); emit Lens_AccessControl_RoleRevoked(account, roleId); @@ -157,6 +157,8 @@ contract RoleBasedAccessControl is IRoleBasedAccessControl { virtual returns (bool) { + require(contractAddress != ANY_CONTRACT_ADDRESS, Errors.InvalidParameter()); + require(permissionId != ANY_PERMISSION_ID, Errors.InvalidParameter()); for (uint256 i = 0; i < _roles[account].length; i++) { if (_hasAccess(_roles[account][i], contractAddress, permissionId)) { // GRANTED-overrides strategy @@ -172,9 +174,6 @@ contract RoleBasedAccessControl is IRoleBasedAccessControl { virtual returns (bool) { - require(contractAddress != ANY_CONTRACT_ADDRESS, Errors.InvalidParameter()); - require(permissionId != ANY_PERMISSION_ID, Errors.InvalidParameter()); - Access fullySpecifiedAccess = _access[roleId][contractAddress][permissionId]; if (fullySpecifiedAccess != Access.UNDEFINED) { From b1652f7c1f96dfabcad410e224265a270f0e3f69 Mon Sep 17 00:00:00 2001 From: Alan Donoso Naumczuk Date: Fri, 17 Jan 2025 14:52:16 -0300 Subject: [PATCH 34/41] misc: proxy__ prefix added to BeaconProxy functions --- contracts/core/upgradeability/BeaconProxy.sol | 14 +++++++------- contracts/core/upgradeability/ProxyAdmin.sol | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/contracts/core/upgradeability/BeaconProxy.sol b/contracts/core/upgradeability/BeaconProxy.sol index d11a2b92..b7764495 100644 --- a/contracts/core/upgradeability/BeaconProxy.sol +++ b/contracts/core/upgradeability/BeaconProxy.sol @@ -62,26 +62,26 @@ contract BeaconProxy { _fetchImplFromBeaconAndAutoUpgradeIfNeeded(); } - function changeProxyAdmin(address proxyAdmin) external { + function proxy__changeProxyAdmin(address proxyAdmin) external { require(msg.sender == $proxyAdmin().value, Errors.InvalidMsgSender()); $proxyAdmin().value = proxyAdmin; emit AdminChanged(msg.sender, proxyAdmin); } - function optOutFromAutoUpgrade() external { + function proxy__optOutFromAutoUpgrade() external { require(msg.sender == $proxyAdmin().value, Errors.InvalidMsgSender()); $autoUpgrade().value = false; emit AutoUpgradeChanged(false); } - function optInToAutoUpgrade() external { + function proxy__optInToAutoUpgrade() external { require(msg.sender == $proxyAdmin().value, Errors.InvalidMsgSender()); $autoUpgrade().value = true; emit AutoUpgradeChanged(true); _fetchImplFromBeaconAndAutoUpgradeIfNeeded(); } - function setImplementation(address implementation) external { + function proxy__setImplementation(address implementation) external { require(msg.sender == $proxyAdmin().value, Errors.InvalidMsgSender()); require($autoUpgrade().value == false, Errors.AutoUpgradeEnabled()); if (implementation != $implementation().value) { @@ -90,7 +90,7 @@ contract BeaconProxy { } } - function setBeacon(address beacon) external { + function proxy__setBeacon(address beacon) external { require(msg.sender == $proxyAdmin().value, Errors.InvalidMsgSender()); if (beacon != $beacon().value) { $beacon().value = beacon; @@ -101,7 +101,7 @@ contract BeaconProxy { } } - function triggerUpgradeToVersion(uint256 implementationVersion) external { + function proxy__triggerUpgradeToVersion(uint256 implementationVersion) external { require(msg.sender == $proxyAdmin().value, Errors.InvalidMsgSender()); address implementationFromBeacon = IVersionedBeacon($beacon().value).implementation(implementationVersion); if (implementationFromBeacon != $implementation().value) { @@ -110,7 +110,7 @@ contract BeaconProxy { } } - function triggerUpgrade() external { + function proxy__triggerUpgrade() external { require(msg.sender == $proxyAdmin().value, Errors.InvalidMsgSender()); _fetchImplFromBeaconAndAutoUpgradeIfNeeded(); } diff --git a/contracts/core/upgradeability/ProxyAdmin.sol b/contracts/core/upgradeability/ProxyAdmin.sol index fe0e3f65..b6a92048 100644 --- a/contracts/core/upgradeability/ProxyAdmin.sol +++ b/contracts/core/upgradeability/ProxyAdmin.sol @@ -24,18 +24,18 @@ contract ProxyAdmin is Ownable { if (LOCK.isLocked()) { // While the Proxy Admin is locked it: // - Cannot change Proxy Admin in the Proxy, only in the ProxyAdmin contract itself - require(selector != BeaconProxy.changeProxyAdmin.selector, Errors.Locked()); + require(selector != BeaconProxy.proxy__changeProxyAdmin.selector, Errors.Locked()); // - Cannot change the Beacon in the Proxy - require(selector != BeaconProxy.setBeacon.selector, Errors.Locked()); + require(selector != BeaconProxy.proxy__setBeacon.selector, Errors.Locked()); // - Cannot change the implementation in the Proxy - require(selector != BeaconProxy.setImplementation.selector, Errors.Locked()); + require(selector != BeaconProxy.proxy__setImplementation.selector, Errors.Locked()); // - Cannot trigger an upgrade in the Proxy - require(selector != BeaconProxy.triggerUpgradeToVersion.selector, Errors.Locked()); - require(selector != BeaconProxy.triggerUpgrade.selector, Errors.Locked()); + require(selector != BeaconProxy.proxy__triggerUpgradeToVersion.selector, Errors.Locked()); + require(selector != BeaconProxy.proxy__triggerUpgrade.selector, Errors.Locked()); // - Cannot opt-out from auto-upgrade in the Proxy - require(selector != BeaconProxy.optOutFromAutoUpgrade.selector, Errors.Locked()); + require(selector != BeaconProxy.proxy__optOutFromAutoUpgrade.selector, Errors.Locked()); // - Cannot opt-in to auto-upgrade in the Proxy - require(selector != BeaconProxy.optInToAutoUpgrade.selector, Errors.Locked()); + require(selector != BeaconProxy.proxy__optInToAutoUpgrade.selector, Errors.Locked()); } // Do the call (bool callSucceeded, bytes memory ret) = to.safecall(value, data); From 95176ad33a9b5aeebc3e0ca76028815d76976d94 Mon Sep 17 00:00:00 2001 From: vicnaum Date: Fri, 17 Jan 2025 19:17:16 +0100 Subject: [PATCH 35/41] fix: make all the rule-related hooks abstract and required to override --- contracts/core/base/RuleBasedPrimitive.sol | 11 ++++----- contracts/core/primitives/feed/Feed.sol | 5 ++-- .../core/primitives/feed/RuleBasedFeed.sol | 19 +++++++++++---- .../core/primitives/graph/RuleBasedGraph.sol | 9 +++++++ contracts/core/primitives/group/Group.sol | 7 ++++++ .../core/primitives/group/RuleBasedGroup.sol | 24 +++++++++++++++++++ .../core/primitives/namespace/Namespace.sol | 12 ++++++++-- .../namespace/RuleBasedNamespace.sol | 24 +++++++++++++++++++ 8 files changed, 96 insertions(+), 15 deletions(-) diff --git a/contracts/core/base/RuleBasedPrimitive.sol b/contracts/core/base/RuleBasedPrimitive.sol index f93ddf96..096646e0 100644 --- a/contracts/core/base/RuleBasedPrimitive.sol +++ b/contracts/core/base/RuleBasedPrimitive.sol @@ -120,8 +120,7 @@ abstract contract RuleBasedPrimitive { internal pure virtual - returns (bytes memory) - {} + returns (bytes memory); function _emitEntityRuleConfiguredEvent( bool wasAlreadyConfigured, @@ -129,7 +128,7 @@ abstract contract RuleBasedPrimitive { address ruleAddress, bytes32 configSalt, KeyValue[] memory ruleParams - ) internal virtual {} + ) internal virtual; function _emitEntityRuleSelectorEvent( bool enabled, @@ -138,7 +137,7 @@ abstract contract RuleBasedPrimitive { bytes32 configSalt, bool isRequired, bytes4 selector - ) internal virtual {} + ) internal virtual; // Internal @@ -221,9 +220,9 @@ abstract contract RuleBasedPrimitive { } } - function _beforeChangePrimitiveRules(RuleChange[] memory ruleChanges) internal virtual {} + function _beforeChangePrimitiveRules(RuleChange[] memory ruleChanges) internal virtual; - function _beforeChangeEntityRules(uint256 entityId, RuleChange[] memory ruleChanges) internal virtual {} + function _beforeChangeEntityRules(uint256 entityId, RuleChange[] memory ruleChanges) internal virtual; function _configureRule( RulesStorage storage rulesStorage, diff --git a/contracts/core/primitives/feed/Feed.sol b/contracts/core/primitives/feed/Feed.sol index 64a2b1ca..5827f8b9 100644 --- a/contracts/core/primitives/feed/Feed.sol +++ b/contracts/core/primitives/feed/Feed.sol @@ -65,16 +65,17 @@ contract Feed is // Access Controlled functions - function _beforeMetadataURIUpdate(string memory /* metadataURI */ ) internal view override { + function _beforeMetadataURIUpdate(string memory /* metadataURI */ ) internal view virtual override { _requireAccess(msg.sender, PID__SET_METADATA); } - function _beforeChangePrimitiveRules(RuleChange[] memory /* ruleChanges */ ) internal virtual override { + function _beforeChangePrimitiveRules(RuleChange[] memory /* ruleChanges */ ) internal view virtual override { _requireAccess(msg.sender, PID__CHANGE_RULES); } function _beforeChangeEntityRules(uint256 entityId, RuleChange[] memory /* ruleChanges */ ) internal + view virtual override { diff --git a/contracts/core/primitives/feed/RuleBasedFeed.sol b/contracts/core/primitives/feed/RuleBasedFeed.sol index 39fbc66b..7b11cddd 100644 --- a/contracts/core/primitives/feed/RuleBasedFeed.sol +++ b/contracts/core/primitives/feed/RuleBasedFeed.sol @@ -47,17 +47,17 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { function changePostRules( uint256 postId, RuleChange[] calldata ruleChanges, - RuleProcessingParams[] calldata ruleChangesProcessingParams + RuleProcessingParams[] calldata feedRulesParams ) external virtual override { - _changeEntityRules($postRulesStorage(postId), postId, ruleChanges, ruleChangesProcessingParams); + _changeEntityRules($postRulesStorage(postId), postId, ruleChanges, feedRulesParams); } function _processEntityRulesChanges( - uint256 entityId, + uint256 postId, RuleChange[] memory ruleChanges, - RuleProcessingParams[] memory ruleChangesProcessingParams + RuleProcessingParams[] memory feedRulesParams ) internal virtual override { - _processPostRulesChanges(entityId, ruleChanges, ruleChangesProcessingParams); + _processPostRulesChanges(postId, ruleChanges, feedRulesParams); } function _supportedPrimitiveRuleSelectors() internal view virtual override returns (bytes4[] memory) { @@ -85,6 +85,15 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { return abi.encodeCall(IFeedRule.configure, (configSalt, ruleParams)); } + function _encodeEntityConfigureCall(uint256 postId, bytes32 configSalt, KeyValue[] memory ruleParams) + internal + pure + override + returns (bytes memory) + { + return abi.encodeCall(IPostRule.configure, (configSalt, postId, ruleParams)); + } + function _emitPrimitiveRuleConfiguredEvent( bool wasAlreadyConfigured, address ruleAddress, diff --git a/contracts/core/primitives/graph/RuleBasedGraph.sol b/contracts/core/primitives/graph/RuleBasedGraph.sol index da76c217..5279b736 100644 --- a/contracts/core/primitives/graph/RuleBasedGraph.sol +++ b/contracts/core/primitives/graph/RuleBasedGraph.sol @@ -84,6 +84,15 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive { return abi.encodeCall(IGraphRule.configure, (configSalt, ruleParams)); } + function _encodeEntityConfigureCall(uint256 accountAsUint256, bytes32 configSalt, KeyValue[] memory ruleParams) + internal + pure + override + returns (bytes memory) + { + return abi.encodeCall(IFollowRule.configure, (configSalt, address(uint160(accountAsUint256)), ruleParams)); + } + function _emitPrimitiveRuleConfiguredEvent( bool wasAlreadyConfigured, address ruleAddress, diff --git a/contracts/core/primitives/group/Group.sol b/contracts/core/primitives/group/Group.sol index 77d55c7c..30ebbe8d 100644 --- a/contracts/core/primitives/group/Group.sol +++ b/contracts/core/primitives/group/Group.sol @@ -75,6 +75,13 @@ contract Group is _requireAccess(msg.sender, PID__CHANGE_RULES); } + function _beforeChangeEntityRules(uint256 entityId, RuleChange[] memory ruleChanges) + internal + pure + virtual + override + {} + function setExtraData(KeyValue[] calldata extraDataToSet) external override { _requireAccess(msg.sender, PID__SET_EXTRA_DATA); for (uint256 i = 0; i < extraDataToSet.length; i++) { diff --git a/contracts/core/primitives/group/RuleBasedGroup.sol b/contracts/core/primitives/group/RuleBasedGroup.sol index 4ff96ca1..76ba8e26 100644 --- a/contracts/core/primitives/group/RuleBasedGroup.sol +++ b/contracts/core/primitives/group/RuleBasedGroup.sol @@ -55,6 +55,13 @@ abstract contract RuleBasedGroup is IGroup, RuleBasedPrimitive { return abi.encodeCall(IGroupRule.configure, (configSalt, ruleParams)); } + function _encodeEntityConfigureCall(uint256 entityId, bytes32 configSalt, KeyValue[] memory ruleParams) + internal + pure + override + returns (bytes memory) + {} + function _emitPrimitiveRuleConfiguredEvent( bool wasAlreadyConfigured, address ruleAddress, @@ -82,6 +89,23 @@ abstract contract RuleBasedGroup is IGroup, RuleBasedPrimitive { } } + function _emitEntityRuleConfiguredEvent( + bool wasAlreadyConfigured, + uint256 entityId, + address ruleAddress, + bytes32 configSalt, + KeyValue[] memory ruleParams + ) internal override {} + + function _emitEntityRuleSelectorEvent( + bool enabled, + uint256 entityId, + address ruleAddress, + bytes32 configSalt, + bool isRequired, + bytes4 selector + ) internal override {} + function _amountOfRules(bytes4 ruleSelector) internal view returns (uint256) { return $groupRulesStorage()._getRulesArray(ruleSelector, false).length + $groupRulesStorage()._getRulesArray(ruleSelector, true).length; diff --git a/contracts/core/primitives/namespace/Namespace.sol b/contracts/core/primitives/namespace/Namespace.sol index 0bffc812..bf096e76 100644 --- a/contracts/core/primitives/namespace/Namespace.sol +++ b/contracts/core/primitives/namespace/Namespace.sol @@ -85,13 +85,21 @@ contract Namespace is _requireAccess(msg.sender, PID__SET_METADATA); } - function _beforeTokenURIProviderSet(ITokenURIProvider /* tokenURIProvider */ ) internal view override { + function _beforeTokenURIProviderSet(ITokenURIProvider /* tokenURIProvider */ ) internal view virtual override { _requireAccess(msg.sender, PID__SET_TOKEN_URI_PROVIDER); } - function _beforeChangePrimitiveRules(RuleChange[] memory /* ruleChanges */ ) internal virtual override { + function _beforeChangePrimitiveRules(RuleChange[] memory /* ruleChanges */ ) internal view virtual override { _requireAccess(msg.sender, PID__CHANGE_RULES); } + + function _beforeChangeEntityRules(uint256 entityId, RuleChange[] memory ruleChanges) + internal + pure + virtual + override + {} + // Permissionless functions function createAndAssignUsername( diff --git a/contracts/core/primitives/namespace/RuleBasedNamespace.sol b/contracts/core/primitives/namespace/RuleBasedNamespace.sol index 7fabc7d8..32e0feb4 100644 --- a/contracts/core/primitives/namespace/RuleBasedNamespace.sol +++ b/contracts/core/primitives/namespace/RuleBasedNamespace.sol @@ -55,6 +55,13 @@ abstract contract RuleBasedNamespace is INamespace, RuleBasedPrimitive { return abi.encodeCall(INamespaceRule.configure, (configSalt, ruleParams)); } + function _encodeEntityConfigureCall(uint256 entityId, bytes32 configSalt, KeyValue[] memory ruleParams) + internal + pure + override + returns (bytes memory) + {} + function _emitPrimitiveRuleConfiguredEvent( bool wasAlreadyConfigured, address ruleAddress, @@ -82,6 +89,23 @@ abstract contract RuleBasedNamespace is INamespace, RuleBasedPrimitive { } } + function _emitEntityRuleConfiguredEvent( + bool wasAlreadyConfigured, + uint256 entityId, + address ruleAddress, + bytes32 configSalt, + KeyValue[] memory ruleParams + ) internal override {} + + function _emitEntityRuleSelectorEvent( + bool enabled, + uint256 entityId, + address ruleAddress, + bytes32 configSalt, + bool isRequired, + bytes4 selector + ) internal override {} + function _amountOfRules(bytes4 ruleSelector) internal view returns (uint256) { return $namespaceRulesStorage()._getRulesArray(ruleSelector, false).length + $namespaceRulesStorage()._getRulesArray(ruleSelector, true).length; From 7395e0524c8a693eab94f840f97fbe1df4e2538a Mon Sep 17 00:00:00 2001 From: Alan Donoso Naumczuk Date: Fri, 17 Jan 2025 18:07:58 -0300 Subject: [PATCH 36/41] feat: handledcall and handledsafecall added to CallLib --- contracts/core/libraries/CallLib.sol | 43 ++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/contracts/core/libraries/CallLib.sol b/contracts/core/libraries/CallLib.sol index 8351ae2f..5b2a9c95 100644 --- a/contracts/core/libraries/CallLib.sol +++ b/contracts/core/libraries/CallLib.sol @@ -5,19 +5,50 @@ pragma solidity ^0.8.26; import {Errors} from "contracts/core/types/Errors.sol"; library CallLib { - function safecall(address target, bytes memory data) internal returns (bool, bytes memory) { - (bool callSucceeded, bytes memory returnData) = target.call(data); + function safecall(address target, uint256 value, bytes memory data) internal returns (bool, bytes memory) { + (bool callSucceeded, bytes memory returnData) = target.call{value: value}(data); if (callSucceeded) { require(returnData.length != 0 || target.code.length != 0, Errors.NotAContract()); } return (callSucceeded, returnData); } - function safecall(address target, uint256 value, bytes memory data) internal returns (bool, bytes memory) { + function handledcall(address target, uint256 value, bytes memory data) internal returns (bytes memory) { (bool callSucceeded, bytes memory returnData) = target.call{value: value}(data); - if (callSucceeded) { - require(returnData.length != 0 || target.code.length != 0, Errors.NotAContract()); + return _handleCall(callSucceeded, returnData); + } + + function handledsafecall(address target, uint256 value, bytes memory data) internal returns (bytes memory) { + (bool callSucceeded, bytes memory returnData) = safecall(target, value, data); + return _handleCall(callSucceeded, returnData); + } + + function safecall(address target, bytes memory data) internal returns (bool, bytes memory) { + return safecall(target, 0, data); + } + + function handledcall(address target, bytes memory data) internal returns (bytes memory) { + return handledcall(target, 0, data); + } + + function handledsafecall(address target, bytes memory data) internal returns (bytes memory) { + return handledsafecall(target, 0, data); + } + + function _handleCall(bool callSucceeded, bytes memory returnData) private returns (bytes memory) { + if (!callSucceeded) { + assembly { + // Get the length of the return data, which contains the error message or selector, as the call failed + let length := mload(returnData) + // If the returned data length is greater than zero... + if iszero(iszero(length)) { + // ...revert with the same error message or selector + revert(add(returnData, 32), length) + } + // else, revert without any error message nor selector + revert(0, 0) + } } - return (callSucceeded, returnData); + return returnData; } } From a0bb8969f65abff79ae75bc210c9b723093e2144 Mon Sep 17 00:00:00 2001 From: Alan Donoso Naumczuk Date: Fri, 17 Jan 2025 18:11:18 -0300 Subject: [PATCH 37/41] fix: properly retrieve selector from ProxyAdmin call's calldata --- contracts/core/upgradeability/ProxyAdmin.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/core/upgradeability/ProxyAdmin.sol b/contracts/core/upgradeability/ProxyAdmin.sol index b6a92048..67a3eb33 100644 --- a/contracts/core/upgradeability/ProxyAdmin.sol +++ b/contracts/core/upgradeability/ProxyAdmin.sol @@ -20,7 +20,7 @@ contract ProxyAdmin is Ownable { } function call(address to, uint256 value, bytes calldata data) external onlyOwner returns (bytes memory) { - bytes4 selector = bytes4(data[0]); + bytes4 selector = bytes4(data); if (LOCK.isLocked()) { // While the Proxy Admin is locked it: // - Cannot change Proxy Admin in the Proxy, only in the ProxyAdmin contract itself From 96c48f601a79a6b8a60960d615ff68c469f32870 Mon Sep 17 00:00:00 2001 From: Alan Donoso Naumczuk Date: Fri, 17 Jan 2025 18:11:44 -0300 Subject: [PATCH 38/41] fix: Use handled flavour for safecall and call when needed --- contracts/core/upgradeability/ProxyAdmin.sol | 11 +---------- contracts/extensions/account/Account.sol | 14 +++++--------- 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/contracts/core/upgradeability/ProxyAdmin.sol b/contracts/core/upgradeability/ProxyAdmin.sol index 67a3eb33..2022feb2 100644 --- a/contracts/core/upgradeability/ProxyAdmin.sol +++ b/contracts/core/upgradeability/ProxyAdmin.sol @@ -37,15 +37,6 @@ contract ProxyAdmin is Ownable { // - Cannot opt-in to auto-upgrade in the Proxy require(selector != BeaconProxy.proxy__optInToAutoUpgrade.selector, Errors.Locked()); } - // Do the call - (bool callSucceeded, bytes memory ret) = to.safecall(value, data); - if (!callSucceeded) { - assembly { - // Equivalent to reverting with the returned error selector if the length is not zero. - let length := mload(ret) - if iszero(iszero(length)) { revert(add(ret, 32), length) } - } - } - return ret; + return to.handledsafecall(value, data); } } diff --git a/contracts/extensions/account/Account.sol b/contracts/extensions/account/Account.sol index 1acbcdaa..d1dfe72d 100644 --- a/contracts/extensions/account/Account.sol +++ b/contracts/extensions/account/Account.sol @@ -13,8 +13,11 @@ import {ExtraStorageBased} from "contracts/core/base/ExtraStorageBased.sol"; import {MetadataBased} from "contracts/core/base/MetadataBased.sol"; import {Initializable} from "contracts/core/upgradeability/Initializable.sol"; import {Errors} from "contracts/core/types/Errors.sol"; +import {CallLib} from "contracts/core/libraries/CallLib.sol"; contract Account is IAccount, Initializable, Ownable, IERC721Receiver, ExtraStorageBased, MetadataBased { + using CallLib for address; + // TODO: Think how long the timelock should be and should it be configurable uint256 constant SPENDING_TIMELOCK = 1 hours; @@ -156,16 +159,9 @@ contract Account is IAccount, Initializable, Ownable, IERC721Receiver, ExtraStor require($storage().accountManagerPermissions[msg.sender].canTransferTokens, Errors.NotAllowed()); } } - (bool callSucceeded, bytes memory ret) = to.call{value: value}(data); - if (!callSucceeded) { - assembly { - // Equivalent to reverting with the returned error selector if the length is not zero. - let length := mload(ret) - if iszero(iszero(length)) { revert(add(ret, 32), length) } - } - } + bytes memory returnData = to.handledcall(value, data); emit Lens_Account_TransactionExecuted(to, value, data, msg.sender); - return ret; + return returnData; } receive() external payable override {} From f458e576d521fdf728b8b0648c603fd1d8eb4a2e Mon Sep 17 00:00:00 2001 From: vicnaum Date: Sat, 18 Jan 2025 20:33:48 +0100 Subject: [PATCH 39/41] misc: processRemovePost renamed to processDeletePost --- contracts/core/interfaces/IFeedRule.sol | 2 +- contracts/core/primitives/feed/Feed.sol | 2 +- contracts/core/primitives/feed/RuleBasedFeed.sol | 10 +++++----- contracts/rules/base/AccountBlockingRule.sol | 2 +- contracts/rules/feed/GroupGatedFeedRule.sol | 2 +- contracts/rules/feed/RestrictedSignersFeedRule.sol | 4 ++-- contracts/rules/feed/SimplePaymentFeedRule.sol | 2 +- contracts/rules/feed/TokenGatedFeedRule.sol | 2 +- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/contracts/core/interfaces/IFeedRule.sol b/contracts/core/interfaces/IFeedRule.sol index 1b082c0f..a8dc219c 100644 --- a/contracts/core/interfaces/IFeedRule.sol +++ b/contracts/core/interfaces/IFeedRule.sol @@ -24,7 +24,7 @@ interface IFeedRule { KeyValue[] calldata ruleParams ) external; - function processRemovePost( + function processDeletePost( bytes32 configSalt, uint256 postId, KeyValue[] calldata primitiveParams, diff --git a/contracts/core/primitives/feed/Feed.sol b/contracts/core/primitives/feed/Feed.sol index 5827f8b9..cf2bc520 100644 --- a/contracts/core/primitives/feed/Feed.sol +++ b/contracts/core/primitives/feed/Feed.sol @@ -194,7 +194,7 @@ contract Feed is address author = Core.$storage().posts[postId].author; require(msg.sender == author || _hasAccess(msg.sender, PID__REMOVE_POST), Errors.InvalidMsgSender()); Core._removePost(postId); - _processPostRemoval(postId, customParams, feedRulesParams); + _processPostDeletion(postId, customParams, feedRulesParams); address source = _processSourceStamp(postId, customParams); emit Lens_Feed_PostDeleted(postId, author, customParams, source); } diff --git a/contracts/core/primitives/feed/RuleBasedFeed.sol b/contracts/core/primitives/feed/RuleBasedFeed.sol index 7b11cddd..06f0c3bb 100644 --- a/contracts/core/primitives/feed/RuleBasedFeed.sol +++ b/contracts/core/primitives/feed/RuleBasedFeed.sol @@ -64,7 +64,7 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { bytes4[] memory selectors = new bytes4[](4); selectors[0] = IFeedRule.processCreatePost.selector; selectors[1] = IFeedRule.processEditPost.selector; - selectors[2] = IFeedRule.processRemovePost.selector; + selectors[2] = IFeedRule.processDeletePost.selector; selectors[3] = IFeedRule.processPostRuleChanges.selector; return selectors; } @@ -417,12 +417,12 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { require(_rulesStorage.anyOfRules[processParams.ruleSelector].length == 0, Errors.AllAnyOfRulesReverted()); } - function _processPostRemoval( + function _processPostDeletion( uint256 postId, KeyValue[] calldata customParams, RuleProcessingParams[] calldata rulesProcessingParams ) internal { - bytes4 ruleSelector = IFeedRule.processRemovePost.selector; + bytes4 ruleSelector = IFeedRule.processDeletePost.selector; Rule memory rule; KeyValue[] memory ruleParams; // Check required rules (AND-combined rules) @@ -430,7 +430,7 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { rule = $feedRulesStorage().requiredRules[ruleSelector][i]; ruleParams = _getRuleParamsOrEmptyArray(rule, rulesProcessingParams); (bool callSucceeded,) = rule.ruleAddress.safecall( - abi.encodeCall(IFeedRule.processRemovePost, (rule.configSalt, postId, customParams, ruleParams)) + abi.encodeCall(IFeedRule.processDeletePost, (rule.configSalt, postId, customParams, ruleParams)) ); require(callSucceeded, Errors.RequiredRuleReverted()); } @@ -439,7 +439,7 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive { rule = $feedRulesStorage().anyOfRules[ruleSelector][i]; ruleParams = _getRuleParamsOrEmptyArray(rule, rulesProcessingParams); (bool callSucceeded,) = rule.ruleAddress.safecall( - abi.encodeCall(IFeedRule.processRemovePost, (rule.configSalt, postId, customParams, ruleParams)) + abi.encodeCall(IFeedRule.processDeletePost, (rule.configSalt, postId, customParams, ruleParams)) ); if (callSucceeded) { return; // If any of the OR-combined rules passed, it means they succeed and we can return diff --git a/contracts/rules/base/AccountBlockingRule.sol b/contracts/rules/base/AccountBlockingRule.sol index 7c3a3280..530b8a17 100644 --- a/contracts/rules/base/AccountBlockingRule.sol +++ b/contracts/rules/base/AccountBlockingRule.sol @@ -97,7 +97,7 @@ contract AccountBlockingRule is IFeedRule, IGraphRule, MetadataBased { revert Errors.NotImplemented(); } - function processRemovePost( + function processDeletePost( bytes32, /* configSalt */ uint256, /* postId */ KeyValue[] calldata, /* primitiveCustomParams */ diff --git a/contracts/rules/feed/GroupGatedFeedRule.sol b/contracts/rules/feed/GroupGatedFeedRule.sol index 133842f7..fd15a001 100644 --- a/contracts/rules/feed/GroupGatedFeedRule.sol +++ b/contracts/rules/feed/GroupGatedFeedRule.sol @@ -56,7 +56,7 @@ contract GroupGatedFeedRule is IFeedRule, MetadataBased { revert Errors.NotImplemented(); } - function processRemovePost( + function processDeletePost( bytes32, /* configSalt */ uint256, /* postId */ KeyValue[] calldata, /* primitiveParams */ diff --git a/contracts/rules/feed/RestrictedSignersFeedRule.sol b/contracts/rules/feed/RestrictedSignersFeedRule.sol index 4bee003a..8d34faea 100644 --- a/contracts/rules/feed/RestrictedSignersFeedRule.sol +++ b/contracts/rules/feed/RestrictedSignersFeedRule.sol @@ -49,7 +49,7 @@ contract RestrictedSignersFeedRule is RestrictedSignersRule, IFeedRule { }); } - function processRemovePost( + function processDeletePost( bytes32 configSalt, uint256 postId, KeyValue[] calldata primitiveParams, @@ -57,7 +57,7 @@ contract RestrictedSignersFeedRule is RestrictedSignersRule, IFeedRule { ) external override { _validateRestrictedSignerMessage({ configSalt: configSalt, - functionSelector: IFeedRule.processRemovePost.selector, + functionSelector: IFeedRule.processDeletePost.selector, abiEncodedFunctionParams: abi.encode(postId, EIP712EncodingLib.encodeForEIP712(primitiveParams)), signature: abi.decode(ruleParams[0].value, (EIP712Signature)) }); diff --git a/contracts/rules/feed/SimplePaymentFeedRule.sol b/contracts/rules/feed/SimplePaymentFeedRule.sol index 029b9d9a..43eb925e 100644 --- a/contracts/rules/feed/SimplePaymentFeedRule.sol +++ b/contracts/rules/feed/SimplePaymentFeedRule.sol @@ -64,7 +64,7 @@ contract SimplePaymentFeedRule is SimplePaymentRule, IFeedRule { revert Errors.NotImplemented(); } - function processRemovePost( + function processDeletePost( bytes32, /* configSalt */ uint256, /* postId */ KeyValue[] calldata, /* primitiveParams */ diff --git a/contracts/rules/feed/TokenGatedFeedRule.sol b/contracts/rules/feed/TokenGatedFeedRule.sol index 3c1cdb32..e67543a8 100644 --- a/contracts/rules/feed/TokenGatedFeedRule.sol +++ b/contracts/rules/feed/TokenGatedFeedRule.sol @@ -63,7 +63,7 @@ contract TokenGatedFeedRule is TokenGatedRule, IFeedRule { revert Errors.NotImplemented(); } - function processRemovePost( + function processDeletePost( bytes32, /* configSalt */ uint256, /* postId */ KeyValue[] calldata, /* primitiveParams */ From f0128a6c96a91a2d3cf5e2d5b5239e03b0f1c570 Mon Sep 17 00:00:00 2001 From: vicnaum Date: Sat, 18 Jan 2025 20:36:53 +0100 Subject: [PATCH 40/41] misc: _handleCall changed to pure --- contracts/core/libraries/CallLib.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/core/libraries/CallLib.sol b/contracts/core/libraries/CallLib.sol index 5b2a9c95..a296f782 100644 --- a/contracts/core/libraries/CallLib.sol +++ b/contracts/core/libraries/CallLib.sol @@ -35,7 +35,7 @@ library CallLib { return handledsafecall(target, 0, data); } - function _handleCall(bool callSucceeded, bytes memory returnData) private returns (bytes memory) { + function _handleCall(bool callSucceeded, bytes memory returnData) private pure returns (bytes memory) { if (!callSucceeded) { assembly { // Get the length of the return data, which contains the error message or selector, as the call failed From d93a72fb2731d4c1d897084f2b7b43cb000e17f0 Mon Sep 17 00:00:00 2001 From: vicnaum Date: Sat, 18 Jan 2025 20:41:18 +0100 Subject: [PATCH 41/41] misc: Renames Self() error to ActionOnSelf() to prevent clashing with Rust reserved keyword --- contracts/core/primitives/graph/GraphCore.sol | 2 +- contracts/core/types/Errors.sol | 2 +- contracts/migration/MigrationGraph.sol | 2 +- contracts/rules/base/AccountBlockingRule.sol | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/contracts/core/primitives/graph/GraphCore.sol b/contracts/core/primitives/graph/GraphCore.sol index 31854742..104e165c 100644 --- a/contracts/core/primitives/graph/GraphCore.sol +++ b/contracts/core/primitives/graph/GraphCore.sol @@ -33,7 +33,7 @@ library GraphCore { { require(followerAccount != address(0), Errors.InvalidParameter()); require(accountToFollow != address(0), Errors.InvalidParameter()); - require(followerAccount != accountToFollow, Errors.Self()); + require(followerAccount != accountToFollow, Errors.ActionOnSelf()); require($storage().follows[followerAccount][accountToFollow].id == 0, Errors.CannotFollowAgain()); if (followId == 0) { followId = ++$storage().lastFollowIdAssigned[accountToFollow]; diff --git a/contracts/core/types/Errors.sol b/contracts/core/types/Errors.sol index 1c60ac68..08b4fef6 100644 --- a/contracts/core/types/Errors.sol +++ b/contracts/core/types/Errors.sol @@ -37,7 +37,7 @@ library Errors { error RequiredRuleReverted(); error RuleNotConfigured(); error SelectorEnabledForDifferentRuleType(); - error Self(); + error ActionOnSelf(); error SingleAnyOfRule(); error UnexpectedContractImpl(); error UnsupportedSelector(); diff --git a/contracts/migration/MigrationGraph.sol b/contracts/migration/MigrationGraph.sol index 0067c3e5..acaadd91 100644 --- a/contracts/migration/MigrationGraph.sol +++ b/contracts/migration/MigrationGraph.sol @@ -39,7 +39,7 @@ contract MigrationGraph is Graph { function _followWithoutChecks(address followerAccount, address accountToFollow, uint256 followId, uint256 timestamp) internal { - require(followerAccount != accountToFollow, Errors.Self()); + require(followerAccount != accountToFollow, Errors.ActionOnSelf()); require(followId != 0, Errors.InvalidParameter()); require(followerAccount != address(0), Errors.InvalidParameter()); require(accountToFollow != address(0), Errors.InvalidParameter()); diff --git a/contracts/rules/base/AccountBlockingRule.sol b/contracts/rules/base/AccountBlockingRule.sol index 530b8a17..6a53a1d1 100644 --- a/contracts/rules/base/AccountBlockingRule.sol +++ b/contracts/rules/base/AccountBlockingRule.sol @@ -34,7 +34,7 @@ contract AccountBlockingRule is IFeedRule, IGraphRule, MetadataBased { function blockUser(address source, address target) external { require(msg.sender == source, Errors.InvalidMsgSender()); - require(source != target, Errors.Self()); + require(source != target, Errors.ActionOnSelf()); accountBlocks[source][target] = block.timestamp; }