Skip to content

Commit

Permalink
Merge pull request #55 from lens-protocol/feat/rules-refactor
Browse files Browse the repository at this point in the history
feat: Refactor rule configuration flow
  • Loading branch information
donosonaumczuk authored Dec 18, 2024
2 parents 73e7bcf + 557f806 commit 45c0715
Show file tree
Hide file tree
Showing 47 changed files with 1,186 additions and 1,272 deletions.
2 changes: 2 additions & 0 deletions contracts/core/base/ExtraStorageBased.sol
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ abstract contract ExtraStorageBased {
return _setExtraData(address(this), entityId, extraDataToSet);
}

// TODO: Currently we don't have a entityBased extraData that doesn't change if the owner is changed. Should we?

// TODO: rename to accent it's user/author-set?
function _setEntityExtraData(uint256 entityId, KeyValue memory extraDataToSet) internal returns (bool) {
return _setExtraData(msg.sender, entityId, extraDataToSet);
Expand Down
235 changes: 235 additions & 0 deletions contracts/core/base/RuleBasedPrimitive.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
// SPDX-License-Identifier: UNLICENSED
// Copyright (C) 2024 Lens Labs. All Rights Reserved.
pragma solidity ^0.8.0;

import {RulesStorage, RulesLib} from "./../libraries/RulesLib.sol";
import {
RuleChange,
RuleConfigurationChange,
RuleSelectorChange,
RuleProcessingParams,
Rule,
KeyValue
} from "./../types/Types.sol";

abstract contract RuleBasedPrimitive {
using RulesLib for RulesStorage;

function _changePrimitiveRules(
RulesStorage storage rulesStorage,
RuleChange[] calldata ruleChanges
) internal virtual {
_changeRules(
rulesStorage,
0,
ruleChanges,
new RuleProcessingParams[](0),
_encodeConfigureCall,
_emitConfiguredEvent,
_emitSelectorEvent
);
}

function _changeEntityRules(
RulesStorage storage rulesStorage,
uint256 entityId,
RuleChange[] calldata ruleChanges,
RuleProcessingParams[] calldata ruleChangesProcessingParams
) internal virtual {
_changeRules(
rulesStorage,
entityId,
ruleChanges,
ruleChangesProcessingParams,
_encodeConfigureCall,
_emitConfiguredEvent,
_emitSelectorEvent
);
}

function _encodeConfigureCall(
uint256 entityId,
bytes32 configSalt,
KeyValue[] calldata ruleParams
) internal pure returns (bytes memory) {
if (entityId == 0) {
return _encodePrimitiveConfigureCall(configSalt, ruleParams);
} else {
return _encodeEntityConfigureCall(entityId, configSalt, ruleParams);
}
}

function _emitConfiguredEvent(
bool wasAlreadyConfigured,
uint256 entityId,
address ruleAddress,
bytes32 configSalt,
KeyValue[] calldata ruleParams
) internal {
if (entityId == 0) {
_emitPrimitiveRuleConfiguredEvent(wasAlreadyConfigured, ruleAddress, configSalt, ruleParams);
} else {
_emitEntityRuleConfiguredEvent(wasAlreadyConfigured, entityId, ruleAddress, configSalt, ruleParams);
}
}

function _emitSelectorEvent(
bool enabled,
uint256 entityId,
address ruleAddress,
bytes32 configSalt,
bool isRequired,
bytes4 selector
) internal {
if (entityId == 0) {
_emitPrimitiveRuleSelectorEvent(enabled, ruleAddress, configSalt, isRequired, selector);
} else {
_emitEntityRuleSelectorEvent(enabled, entityId, ruleAddress, configSalt, isRequired, selector);
}
}

// Primitive functions:

function _encodePrimitiveConfigureCall(
bytes32 configSalt,
KeyValue[] calldata ruleParams
) internal pure virtual returns (bytes memory);

function _emitPrimitiveRuleConfiguredEvent(
bool wasAlreadyConfigured,
address ruleAddress,
bytes32 configSalt,
KeyValue[] calldata ruleParams
) internal virtual;

function _emitPrimitiveRuleSelectorEvent(
bool enabled,
address ruleAddress,
bytes32 configSalt,
bool isRequired,
bytes4 selector
) internal virtual;

// Entity functions:

function _encodeEntityConfigureCall(
uint256 entityId,
bytes32 configSalt,
KeyValue[] calldata ruleParams
) internal pure virtual returns (bytes memory) {}

function _emitEntityRuleConfiguredEvent(
bool wasAlreadyConfigured,
uint256 entityId,
address ruleAddress,
bytes32 configSalt,
KeyValue[] calldata ruleParams
) internal virtual {}

function _emitEntityRuleSelectorEvent(
bool enabled,
uint256 entityId,
address ruleAddress,
bytes32 configSalt,
bool isRequired,
bytes4 selector
) internal virtual {}

// Internal

function _changeRules(
RulesStorage storage rulesStorage,
uint256 entityId,
RuleChange[] calldata 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(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
);
}
for (uint256 j = 0; j < ruleChange.selectorChanges.length; j++) {
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) {
_validateRulesLength(rulesStorage, _supportedPrimitiveRuleSelectors());
} else {
_validateRulesLength(rulesStorage, _supportedEntityRuleSelectors());
_processEntityRulesChanges(entityId, ruleChanges, ruleChangesProcessingParams); // TODO: Which one we pass? The one with configSalt's already assigned or the original one with the zero-ed configSalt's?
}
}

function _supportedPrimitiveRuleSelectors() internal view virtual returns (bytes4[] memory);

function _supportedEntityRuleSelectors() internal view virtual returns (bytes4[] memory) {
return new bytes4[](0);
}

function _beforeChangeRules(uint256 entityId, RuleChange[] calldata ruleChanges) internal virtual {
if (entityId == 0) {
_beforeChangePrimitiveRules(ruleChanges);
} else {
_beforeChangeEntityRules(entityId, ruleChanges);
}
}

function _processEntityRulesChanges(
uint256 entityId,
RuleChange[] calldata ruleChanges,
RuleProcessingParams[] memory ruleChangesProcessingParams
) internal virtual {}

function _validateRulesLength(
RulesStorage storage rulesStorage,
bytes4[] memory selectorsToValidate
) internal view {
for (uint256 i = 0; i < selectorsToValidate.length; i++) {
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");
}
}

function _beforeChangePrimitiveRules(RuleChange[] calldata ruleChanges) internal virtual {}

function _beforeChangeEntityRules(uint256 entityId, RuleChange[] calldata ruleChanges) internal virtual {}

function _configureRule(
RulesStorage storage rulesStorage,
address ruleAddress,
bytes32 providedConfigSalt,
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
) 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);
return configSalt;
}
}
60 changes: 25 additions & 35 deletions contracts/core/interfaces/IFeed.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,7 @@
// Copyright (C) 2024 Lens Labs. All Rights Reserved.
pragma solidity ^0.8.0;

import {
KeyValue,
RuleConfigurationParams_Multiselector,
Rule,
RuleChange,
RuleProcessingParams
} from "./../types/Types.sol";
import {KeyValue, Rule, RuleProcessingParams, RuleChange} from "./../types/Types.sol";
import {IMetadataBased} from "./../interfaces/IMetadataBased.sol";

struct EditPostParams {
Expand All @@ -22,7 +16,7 @@ struct CreatePostParams {
uint256 repostedPostId;
uint256 quotedPostId;
uint256 repliedPostId;
RuleConfigurationParams_Multiselector[] rules;
RuleChange[] ruleChanges;
KeyValue[] extraData;
}

Expand Down Expand Up @@ -75,46 +69,42 @@ interface IFeed is IMetadataBased {
event Lens_Feed_ExtraDataUpdated(bytes32 indexed key, bytes value, bytes indexed valueIndexed);
event Lens_Feed_ExtraDataRemoved(bytes32 indexed key);

event Lens_Feed_RuleAdded(
address indexed rule,
bytes32 indexed configSalt,
bytes4 indexed ruleSelector,
KeyValue[] configParams,
bool isRequired
event Lens_Feed_RuleConfigured(address indexed rule, bytes32 indexed configSalt, KeyValue[] configParams);

event Lens_Feed_RuleReconfigured(address indexed rule, bytes32 indexed configSalt, KeyValue[] configParams);

event Lens_Feed_RuleSelectorEnabled(
address indexed rule, bytes32 indexed configSalt, bool isRequired, bytes4 ruleSelector
);

event Lens_Feed_RuleUpdated(
address indexed rule,
bytes32 indexed configSalt,
bytes4 indexed ruleSelector,
KeyValue[] configParams,
bool isRequired
event Lens_Feed_RuleSelectorDisabled(
address indexed rule, bytes32 indexed configSalt, bool isRequired, bytes4 ruleSelector
);

event Lens_Feed_RuleRemoved(address indexed rule, bytes32 indexed configSalt, bytes4 indexed ruleSelector);
event Lens_Feed_Post_RuleConfigured(
uint256 indexed postId, address author, address indexed rule, bytes32 indexed configSalt, KeyValue[] configParams
);

event Lens_Feed_Post_RuleAdded(
event Lens_Feed_Post_RuleReconfigured(
uint256 indexed postId, address author, address indexed rule, bytes32 indexed configSalt, KeyValue[] configParams
);

event Lens_Feed_Post_RuleSelectorEnabled(
uint256 indexed postId,
address author,
address indexed rule,
bytes32 configSalt,
bytes4 indexed ruleSelector,
KeyValue[] configParams,
bool isRequired
bytes32 indexed configSalt,
bool isRequired,
bytes4 ruleSelector
);

event Lens_Feed_Post_RuleUpdated(
event Lens_Feed_Post_RuleSelectorDisabled(
uint256 indexed postId,
address author,
address indexed rule,
bytes32 configSalt,
bytes4 indexed ruleSelector,
KeyValue[] configParams,
bool isRequired
);

event Lens_Feed_Post_RuleRemoved(
uint256 indexed postId, address author, address indexed rule, bytes32 configSalt, bytes4 indexed ruleSelector
bytes32 indexed configSalt,
bool isRequired,
bytes4 ruleSelector
);

event Lens_Feed_Post_ExtraDataAdded(
Expand Down
16 changes: 8 additions & 8 deletions contracts/core/interfaces/IFeedRule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,35 @@ import {CreatePostParams, EditPostParams} from "./IFeed.sol";
import {KeyValue, RuleChange} from "./../types/Types.sol";

interface IFeedRule {
function configure(bytes4 ruleSelector, bytes32 salt, KeyValue[] calldata ruleConfigurationParams) external;
function configure(bytes32 configSalt, KeyValue[] calldata ruleParams) external;

function processCreatePost(
bytes32 configSalt,
uint256 postId,
CreatePostParams calldata postParams,
KeyValue[] calldata primitiveCustomParams,
KeyValue[] calldata ruleExecutionParams
KeyValue[] calldata primitiveParams,
KeyValue[] calldata ruleParams
) external;

function processEditPost(
bytes32 configSalt,
uint256 postId,
EditPostParams calldata postParams,
KeyValue[] calldata primitiveCustomParams,
KeyValue[] calldata ruleExecutionParams
KeyValue[] calldata primitiveParams,
KeyValue[] calldata ruleParams
) external;

function processRemovePost(
bytes32 configSalt,
uint256 postId,
KeyValue[] calldata primitiveCustomParams,
KeyValue[] calldata ruleExecutionParams
KeyValue[] calldata primitiveParams,
KeyValue[] calldata ruleParams
) external;

function processPostRuleChanges(
bytes32 configSalt,
uint256 postId,
RuleChange[] calldata ruleChanges,
KeyValue[] calldata ruleExecutionParams
KeyValue[] calldata ruleParams
) external;
}
Loading

0 comments on commit 45c0715

Please sign in to comment.