Skip to content

Commit

Permalink
Merge pull request #69 from lens-protocol/code-changes
Browse files Browse the repository at this point in the history
misc: AC injection & CallLib::safecall
  • Loading branch information
joshstevens19 authored Jan 6, 2025
2 parents 9f28983 + 729ca31 commit 1520a6d
Show file tree
Hide file tree
Showing 14 changed files with 194 additions and 131 deletions.
2 changes: 2 additions & 0 deletions contracts/core/base/RuleBasedPrimitive.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ import {
Rule,
KeyValue
} from "contracts/core/types/Types.sol";
import {CallLib} from "contracts/core/libraries/CallLib.sol";

abstract contract RuleBasedPrimitive {
using RulesLib for RulesStorage;
using CallLib for address;

function _changePrimitiveRules(RulesStorage storage rulesStorage, RuleChange[] calldata ruleChanges)
internal
Expand Down
21 changes: 21 additions & 0 deletions contracts/core/libraries/CallLib.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: UNLICENSED
// Copyright (C) 2024 Lens Labs. All Rights Reserved.
pragma solidity ^0.8.17;

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");
}
return (success, 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) {
require(returnData.length != 0 || target.code.length != 0, "NOT_A_CONTRACT");
}
return (success, returnData);
}
}
5 changes: 4 additions & 1 deletion contracts/core/libraries/RulesLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
pragma solidity ^0.8.0;

import {Rule} from "contracts/core/types/Types.sol";
import {CallLib} from "contracts/core/libraries/CallLib.sol";

struct RulesStorage {
mapping(bytes4 => Rule[]) requiredRules;
Expand All @@ -19,6 +20,8 @@ struct RuleState {
}

library RulesLib {
using CallLib for address;

uint256 constant MAX_AMOUNT_OF_RULES = 20;

function generateOrValidateConfigSalt(
Expand All @@ -42,7 +45,7 @@ library RulesLib {
) internal returns (bool) {
bool wasAlreadyConfigured = rulesStorage.isConfigured[ruleAddress][configSalt];
rulesStorage.isConfigured[ruleAddress][configSalt] = true;
(bool success,) = ruleAddress.call(encodedConfigureCall);
(bool success,) = ruleAddress.safecall(encodedConfigureCall);
require(success);
return wasAlreadyConfigured;
}
Expand Down
18 changes: 10 additions & 8 deletions contracts/core/primitives/feed/RuleBasedFeed.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ import {RulesStorage, RulesLib} from "contracts/core/libraries/RulesLib.sol";
import {RuleProcessingParams, Rule, RuleChange, KeyValue} from "contracts/core/types/Types.sol";
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";

abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive {
using RulesLib for RulesStorage;
using CallLib for address;

struct RuleBasedStorage {
RulesStorage feedRulesStorage;
Expand Down Expand Up @@ -141,7 +143,7 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive {
KeyValue[] calldata primitiveCustomParams,
KeyValue[] memory ruleCustomParams
) internal returns (bool, bytes memory) {
return rule.call(
return rule.safecall(
abi.encodeCall(
IFeedRule.processCreatePost, (configSalt, postId, postParams, primitiveCustomParams, ruleCustomParams)
)
Expand All @@ -157,7 +159,7 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive {
KeyValue[] calldata primitiveCustomParams,
KeyValue[] memory ruleCustomParams
) internal returns (bool, bytes memory) {
return rule.call(
return rule.safecall(
abi.encodeCall(
IPostRule.processCreatePost,
(configSalt, rootPostId, postId, postParams, primitiveCustomParams, ruleCustomParams)
Expand Down Expand Up @@ -295,7 +297,7 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive {
KeyValue[] calldata primitiveCustomParams,
KeyValue[] memory ruleCustomParams
) internal returns (bool, bytes memory) {
return rule.call(
return rule.safecall(
abi.encodeCall(
IFeedRule.processEditPost, (configSalt, postId, postParams, primitiveCustomParams, ruleCustomParams)
)
Expand All @@ -311,7 +313,7 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive {
KeyValue[] calldata primitiveCustomParams,
KeyValue[] memory ruleCustomParams
) internal returns (bool, bytes memory) {
return rule.call(
return rule.safecall(
abi.encodeCall(
IPostRule.processEditPost,
(configSalt, rootPostId, postId, postParams, primitiveCustomParams, ruleCustomParams)
Expand Down Expand Up @@ -387,7 +389,7 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive {
) {
ruleCustomParams = rulesProcessingParams[j].ruleParams;
}
(bool callNotReverted,) = rule.ruleAddress.call(
(bool callNotReverted,) = rule.ruleAddress.safecall(
abi.encodeCall(
IFeedRule.processRemovePost, (rule.configSalt, postId, customParams, ruleCustomParams)
)
Expand All @@ -406,7 +408,7 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive {
) {
ruleCustomParams = rulesProcessingParams[j].ruleParams;
}
(bool callNotReverted,) = rule.ruleAddress.call(
(bool callNotReverted,) = rule.ruleAddress.safecall(
abi.encodeCall(
IFeedRule.processRemovePost, (rule.configSalt, postId, customParams, ruleCustomParams)
)
Expand Down Expand Up @@ -437,7 +439,7 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive {
) {
ruleCustomParams = rulesProcessingParams[j].ruleParams;
}
(bool callNotReverted,) = rule.ruleAddress.call(
(bool callNotReverted,) = rule.ruleAddress.safecall(
abi.encodeCall(
IFeedRule.processPostRuleChanges, (rule.configSalt, postId, ruleChanges, ruleCustomParams)
)
Expand All @@ -456,7 +458,7 @@ abstract contract RuleBasedFeed is IFeed, RuleBasedPrimitive {
) {
ruleCustomParams = rulesProcessingParams[j].ruleParams;
}
(bool callNotReverted,) = rule.ruleAddress.call(
(bool callNotReverted,) = rule.ruleAddress.safecall(
abi.encodeCall(
IFeedRule.processPostRuleChanges, (rule.configSalt, postId, ruleChanges, ruleCustomParams)
)
Expand Down
12 changes: 7 additions & 5 deletions contracts/core/primitives/graph/RuleBasedGraph.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ import {RulesStorage, RulesLib} from "contracts/core/libraries/RulesLib.sol";
import {RuleProcessingParams, RuleChange, Rule, KeyValue} from "contracts/core/types/Types.sol";
import {IGraph} from "contracts/core/interfaces/IGraph.sol";
import {RuleBasedPrimitive} from "contracts/core/base/RuleBasedPrimitive.sol";
import {CallLib} from "contracts/core/libraries/CallLib.sol";

abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive {
using RulesLib for RulesStorage;
using CallLib for address;

struct RuleBasedStorage {
RulesStorage graphRulesStorage;
Expand Down Expand Up @@ -144,7 +146,7 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive {
) {
ruleCustomParams = graphRulesProcessingParams[j].ruleParams;
}
(bool callNotReverted,) = rule.ruleAddress.call(
(bool callNotReverted,) = rule.ruleAddress.safecall(
abi.encodeCall(
IGraphRule.processFollowRuleChanges, (rule.configSalt, account, ruleChanges, ruleCustomParams)
)
Expand All @@ -163,7 +165,7 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive {
) {
ruleCustomParams = graphRulesProcessingParams[j].ruleParams;
}
(bool callNotReverted,) = rule.ruleAddress.call(
(bool callNotReverted,) = rule.ruleAddress.safecall(
abi.encodeCall(
IGraphRule.processFollowRuleChanges, (rule.configSalt, account, ruleChanges, ruleCustomParams)
)
Expand All @@ -186,7 +188,7 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive {
KeyValue[] calldata primitiveCustomParams,
KeyValue[] memory ruleCustomParams
) internal returns (bool, bytes memory) {
return rule.call(
return rule.safecall(
abi.encodeCall(
IGraphRule.processFollow,
(
Expand Down Expand Up @@ -229,7 +231,7 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive {
KeyValue[] calldata primitiveCustomParams,
KeyValue[] memory ruleCustomParams
) internal returns (bool, bytes memory) {
return rule.call(
return rule.safecall(
abi.encodeCall(
IGraphRule.processUnfollow,
(
Expand Down Expand Up @@ -271,7 +273,7 @@ abstract contract RuleBasedGraph is IGraph, RuleBasedPrimitive {
KeyValue[] calldata primitiveCustomParams,
KeyValue[] memory ruleCustomParams
) internal returns (bool, bytes memory) {
return rule.call(
return rule.safecall(
abi.encodeCall(
IFollowRule.processFollow,
(
Expand Down
10 changes: 6 additions & 4 deletions contracts/core/primitives/group/RuleBasedGroup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ import {IGroup} from "contracts/core/interfaces/IGroup.sol";
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";

abstract contract RuleBasedGroup is IGroup, RuleBasedPrimitive {
using RulesLib for RulesStorage;
using CallLib for address;

struct RuleBasedStorage {
RulesStorage groupRulesStorage;
Expand Down Expand Up @@ -104,7 +106,7 @@ abstract contract RuleBasedGroup is IGroup, RuleBasedPrimitive {
KeyValue[] calldata primitiveCustomParams,
KeyValue[] memory ruleCustomParams
) internal returns (bool, bytes memory) {
return rule.call(
return rule.safecall(
abi.encodeCall(
IGroupRule.processRemoval,
(configSalt, originalMsgSender, account, primitiveCustomParams, ruleCustomParams)
Expand Down Expand Up @@ -136,7 +138,7 @@ abstract contract RuleBasedGroup is IGroup, RuleBasedPrimitive {
KeyValue[] calldata primitiveCustomParams,
KeyValue[] memory ruleCustomParams
) internal returns (bool, bytes memory) {
return rule.call(
return rule.safecall(
abi.encodeCall(
IGroupRule.processAddition,
(configSalt, originalMsgSender, account, primitiveCustomParams, ruleCustomParams)
Expand Down Expand Up @@ -168,7 +170,7 @@ abstract contract RuleBasedGroup is IGroup, RuleBasedPrimitive {
KeyValue[] calldata primitiveCustomParams,
KeyValue[] memory ruleCustomParams
) internal returns (bool, bytes memory) {
return rule.call(
return rule.safecall(
abi.encodeCall(IGroupRule.processJoining, (configSalt, account, primitiveCustomParams, ruleCustomParams))
);
}
Expand Down Expand Up @@ -197,7 +199,7 @@ abstract contract RuleBasedGroup is IGroup, RuleBasedPrimitive {
KeyValue[] calldata primitiveCustomParams,
KeyValue[] memory ruleCustomParams
) internal returns (bool, bytes memory) {
return rule.call(
return rule.safecall(
abi.encodeCall(IGroupRule.processLeaving, (configSalt, account, primitiveCustomParams, ruleCustomParams))
);
}
Expand Down
10 changes: 6 additions & 4 deletions contracts/core/primitives/namespace/RuleBasedNamespace.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ import {RulesStorage, RulesLib} from "contracts/core/libraries/RulesLib.sol";
import {RuleChange, RuleProcessingParams, Rule, KeyValue} from "contracts/core/types/Types.sol";
import {INamespace} from "contracts/core/interfaces/INamespace.sol";
import {RuleBasedPrimitive} from "contracts/core/base/RuleBasedPrimitive.sol";
import {CallLib} from "contracts/core/libraries/CallLib.sol";

abstract contract RuleBasedNamespace is INamespace, RuleBasedPrimitive {
using RulesLib for RulesStorage;
using CallLib for address;

struct RuleBasedStorage {
RulesStorage namespaceRulesStorage;
Expand Down Expand Up @@ -105,7 +107,7 @@ abstract contract RuleBasedNamespace is INamespace, RuleBasedPrimitive {
KeyValue[] calldata primitiveCustomParams,
KeyValue[] memory ruleCustomParams
) internal returns (bool, bytes memory) {
return rule.call(
return rule.safecall(
abi.encodeCall(
INamespaceRule.processCreation,
(configSalt, originalMsgSender, account, username, primitiveCustomParams, ruleCustomParams)
Expand Down Expand Up @@ -140,7 +142,7 @@ abstract contract RuleBasedNamespace is INamespace, RuleBasedPrimitive {
KeyValue[] calldata primitiveCustomParams,
KeyValue[] memory ruleCustomParams
) internal returns (bool, bytes memory) {
return rule.call(
return rule.safecall(
abi.encodeCall(
INamespaceRule.processRemoval,
(configSalt, originalMsgSender, username, primitiveCustomParams, ruleCustomParams)
Expand Down Expand Up @@ -174,7 +176,7 @@ abstract contract RuleBasedNamespace is INamespace, RuleBasedPrimitive {
KeyValue[] calldata primitiveCustomParams,
KeyValue[] memory ruleCustomParams
) internal returns (bool, bytes memory) {
return rule.call(
return rule.safecall(
abi.encodeCall(
INamespaceRule.processAssigning,
(configSalt, originalMsgSender, account, username, primitiveCustomParams, ruleCustomParams)
Expand Down Expand Up @@ -209,7 +211,7 @@ abstract contract RuleBasedNamespace is INamespace, RuleBasedPrimitive {
KeyValue[] calldata primitiveCustomParams,
KeyValue[] memory ruleCustomParams
) internal returns (bool, bytes memory) {
return rule.call(
return rule.safecall(
abi.encodeCall(
INamespaceRule.processUnassigning,
(configSalt, originalMsgSender, account, username, primitiveCustomParams, ruleCustomParams)
Expand Down
5 changes: 4 additions & 1 deletion contracts/core/upgradeability/ProxyAdmin.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ pragma solidity ^0.8.0;
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";

contract ProxyAdmin is Ownable {
using CallLib for address;

ILock immutable LOCK;

constructor(address proxyAdminOwner, address lock) Ownable() {
Expand Down Expand Up @@ -34,7 +37,7 @@ contract ProxyAdmin is Ownable {
require(selector != BeaconProxy.optInToAutoUpgrade.selector);
}
// Do the call
(bool success, bytes memory ret) = to.call{value: value}(data);
(bool success, bytes memory ret) = to.safecall(value, data);
if (!success) {
assembly {
// Equivalent to reverting with the returned error selector if the length is not zero.
Expand Down
21 changes: 6 additions & 15 deletions contracts/extensions/factories/FeedFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,15 @@ pragma solidity ^0.8.0;

import {IAccessControl} from "contracts/core/interfaces/IAccessControl.sol";
import {Feed} from "contracts/core/primitives/feed/Feed.sol";
import {PermissionlessAccessControl} from "contracts/extensions/access/PermissionlessAccessControl.sol";
import {RuleChange, KeyValue} from "contracts/core/types/Types.sol";
import {IVersionedBeacon} from "contracts/core/interfaces/IVersionedBeacon.sol";
import {BeaconProxy} from "contracts/core/upgradeability/BeaconProxy.sol";
import {ProxyAdmin} from "contracts/core/upgradeability/ProxyAdmin.sol";
import {PrimitiveFactory} from "contracts/extensions/factories/PrimitiveFactory.sol";

contract FeedFactory {
contract FeedFactory is PrimitiveFactory {
event Lens_FeedFactory_Deployment(address indexed feed, string metadataURI);

IAccessControl internal immutable _temporaryAccessControl;
address internal immutable _beacon;
address internal immutable _lock;

constructor(address beacon, address lock) {
_temporaryAccessControl = new PermissionlessAccessControl();
_beacon = beacon;
_lock = lock;
}
constructor(address primitiveBeacon, address proxyAdminLock) PrimitiveFactory(primitiveBeacon, proxyAdminLock) {}

function deployFeed(
string memory metadataURI,
Expand All @@ -30,9 +21,9 @@ contract FeedFactory {
RuleChange[] calldata ruleChanges,
KeyValue[] calldata extraData
) external returns (address) {
address proxyAdmin = address(new ProxyAdmin(proxyAdminOwner, _lock));
Feed feed = Feed(address(new BeaconProxy(proxyAdmin, _beacon)));
feed.initialize(metadataURI, _temporaryAccessControl);
address proxyAdmin = address(new ProxyAdmin(proxyAdminOwner, PROXY_ADMIN_LOCK));
Feed feed = Feed(address(new BeaconProxy(proxyAdmin, PRIMITIVE_BEACON)));
feed.initialize(metadataURI, TEMPORARY_ACCESS_CONTROL);
feed.changeFeedRules(ruleChanges);
feed.setExtraData(extraData);
feed.setAccessControl(accessControl);
Expand Down
21 changes: 6 additions & 15 deletions contracts/extensions/factories/GraphFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,15 @@ pragma solidity ^0.8.0;

import {IAccessControl} from "contracts/core/interfaces/IAccessControl.sol";
import {Graph} from "contracts/core/primitives/graph/Graph.sol";
import {PermissionlessAccessControl} from "contracts/extensions/access/PermissionlessAccessControl.sol";
import {RuleChange, KeyValue} from "contracts/core/types/Types.sol";
import {IVersionedBeacon} from "contracts/core/interfaces/IVersionedBeacon.sol";
import {BeaconProxy} from "contracts/core/upgradeability/BeaconProxy.sol";
import {ProxyAdmin} from "contracts/core/upgradeability/ProxyAdmin.sol";
import {PrimitiveFactory} from "contracts/extensions/factories/PrimitiveFactory.sol";

contract GraphFactory {
contract GraphFactory is PrimitiveFactory {
event Lens_GraphFactory_Deployment(address indexed graph, string metadataURI);

IAccessControl internal immutable _temporaryAccessControl;
address internal immutable _beacon;
address internal immutable _proxyBeaconLock;

constructor(address beacon, address proxyBeaconLock) {
_temporaryAccessControl = new PermissionlessAccessControl();
_beacon = beacon;
_proxyBeaconLock = proxyBeaconLock;
}
constructor(address primitiveBeacon, address proxyAdminLock) PrimitiveFactory(primitiveBeacon, proxyAdminLock) {}

function deployGraph(
string memory metadataURI,
Expand All @@ -30,9 +21,9 @@ contract GraphFactory {
RuleChange[] calldata ruleChanges,
KeyValue[] calldata extraData
) external returns (address) {
address proxyAdmin = address(new ProxyAdmin(proxyAdminOwner, _proxyBeaconLock));
Graph graph = Graph(address(new BeaconProxy(proxyAdmin, _beacon)));
graph.initialize(metadataURI, _temporaryAccessControl);
address proxyAdmin = address(new ProxyAdmin(proxyAdminOwner, PROXY_ADMIN_LOCK));
Graph graph = Graph(address(new BeaconProxy(proxyAdmin, PRIMITIVE_BEACON)));
graph.initialize(metadataURI, TEMPORARY_ACCESS_CONTROL);
graph.changeGraphRules(ruleChanges);
graph.setExtraData(extraData);
graph.setAccessControl(accessControl);
Expand Down
Loading

0 comments on commit 1520a6d

Please sign in to comment.