refactor: Refactored PublishingLogic into GeneralLib, moved more admin logic to GeneralLib.

This commit is contained in:
Peter Michael
2022-06-02 14:24:48 -04:00
parent b8b76f5257
commit bc4bf9807c
11 changed files with 135 additions and 122 deletions

View File

@@ -10,7 +10,7 @@ import {Helpers} from '../libraries/Helpers.sol';
import {Constants} from '../libraries/Constants.sol';
import {DataTypes} from '../libraries/DataTypes.sol';
import {Errors} from '../libraries/Errors.sol';
import {PublishingLogic} from '../libraries/PublishingLogic.sol';
import {GeneralLib} from '../libraries/GeneralLib.sol';
import {ProfileTokenURILogic} from '../libraries/ProfileTokenURILogic.sol';
import {InteractionLogic} from '../libraries/InteractionLogic.sol';
import {MetaTxLib} from '../libraries/MetaTxLib.sol';
@@ -73,7 +73,7 @@ contract LensHub is
address newGovernance
) external override initializer {
super._initialize(name, symbol);
_setState(DataTypes.ProtocolState.Paused);
GeneralLib.setStateSimple(DataTypes.ProtocolState.Paused);
_setGovernance(newGovernance);
}
@@ -88,26 +88,12 @@ contract LensHub is
/// @inheritdoc ILensHub
function setEmergencyAdmin(address newEmergencyAdmin) external override onlyGov {
address prevEmergencyAdmin = _emergencyAdmin;
_emergencyAdmin = newEmergencyAdmin;
emit Events.EmergencyAdminSet(
msg.sender,
prevEmergencyAdmin,
newEmergencyAdmin,
block.timestamp
);
GeneralLib.setEmergencyAdmin(newEmergencyAdmin);
}
/// @inheritdoc ILensHub
function setState(DataTypes.ProtocolState newState) external override {
if (msg.sender == _emergencyAdmin) {
if (newState == DataTypes.ProtocolState.Unpaused)
revert Errors.EmergencyAdminCannotUnpause();
_validateNotPaused();
} else if (msg.sender != _governance) {
revert Errors.NotGovernanceOrEmergencyAdmin();
}
_setState(newState);
GeneralLib.setStateFull(newState);
}
///@inheritdoc ILensHub
@@ -181,12 +167,7 @@ contract LensHub is
unchecked {
uint256 profileId = ++_profileCounter;
_mint(vars.to, profileId);
PublishingLogic.createProfile(
vars,
profileId,
_profileIdByHandleHash,
_profileById
);
GeneralLib.createProfile(vars, profileId, _profileIdByHandleHash, _profileById);
return profileId;
}
}
@@ -213,7 +194,7 @@ contract LensHub is
bytes calldata followModuleInitData
) external override whenNotPaused {
_validateCallerIsProfileOwner(profileId);
PublishingLogic.setFollowModule(
GeneralLib.setFollowModule(
profileId,
followModule,
followModuleInitData,
@@ -228,7 +209,7 @@ contract LensHub is
whenNotPaused
{
MetaTxLib.baseSetFollowModuleWithSig(vars);
PublishingLogic.setFollowModule(
GeneralLib.setFollowModule(
vars.profileId,
vars.followModule,
vars.followModuleInitData,
@@ -743,9 +724,7 @@ contract LensHub is
/// ****************************
function _setGovernance(address newGovernance) internal {
address prevGovernance = _governance;
_governance = newGovernance;
emit Events.GovernanceSet(msg.sender, prevGovernance, newGovernance, block.timestamp);
GeneralLib.setGovernance(newGovernance);
}
function _createPost(
@@ -758,7 +737,7 @@ contract LensHub is
) internal returns (uint256) {
unchecked {
uint256 pubId = ++_profileById[profileId].pubCount;
PublishingLogic.createPost(
GeneralLib.createPost(
profileId,
contentURI,
collectModule,
@@ -788,12 +767,7 @@ contract LensHub is
function _createComment(DataTypes.CommentData memory vars) internal returns (uint256) {
unchecked {
uint256 pubId = ++_profileById[vars.profileId].pubCount;
PublishingLogic.createComment(
vars,
pubId,
_profileById,
_pubByIdByProfile
);
GeneralLib.createComment(vars, pubId, _profileById, _pubByIdByProfile);
return pubId;
}
}
@@ -801,11 +775,7 @@ contract LensHub is
function _createMirror(DataTypes.MirrorData memory vars) internal returns (uint256) {
unchecked {
uint256 pubId = ++_profileById[vars.profileId].pubCount;
PublishingLogic.createMirror(
vars,
pubId,
_pubByIdByProfile
);
GeneralLib.createMirror(vars, pubId, _pubByIdByProfile);
return pubId;
}
}

View File

@@ -15,7 +15,7 @@ import {Errors} from '../../libraries/Errors.sol';
* whenPublishingEnabled: When Unpaused only.
*/
abstract contract LensMultiState {
DataTypes.ProtocolState private _state;
DataTypes.ProtocolState private _state; // slot 14
modifier whenNotPaused() {
_validateNotPaused();
@@ -39,11 +39,11 @@ abstract contract LensMultiState {
return _state;
}
function _setState(DataTypes.ProtocolState newState) internal {
DataTypes.ProtocolState prevState = _state;
_state = newState;
emit Events.StateSet(msg.sender, prevState, newState, block.timestamp);
}
// function _setState(DataTypes.ProtocolState newState) internal {
// DataTypes.ProtocolState prevState = _state;
// _state = newState;
// emit Events.StateSet(msg.sender, prevState, newState, block.timestamp);
// }
function _validatePublishingEnabled() internal view {
if (_state != DataTypes.ProtocolState.Unpaused) {

View File

@@ -13,53 +13,12 @@ import {DataTypes} from '../../libraries/DataTypes.sol';
* storage variables should be done solely at the bottom of this contract.
*/
abstract contract LensHubStorage {
bytes32 internal constant SET_DEFAULT_PROFILE_WITH_SIG_TYPEHASH =
keccak256(
'SetDefaultProfileWithSig(address wallet,uint256 profileId,uint256 nonce,uint256 deadline)'
);
bytes32 internal constant SET_FOLLOW_MODULE_WITH_SIG_TYPEHASH =
keccak256(
'SetFollowModuleWithSig(uint256 profileId,address followModule,bytes followModuleInitData,uint256 nonce,uint256 deadline)'
);
bytes32 internal constant SET_FOLLOW_NFT_URI_WITH_SIG_TYPEHASH =
keccak256(
'SetFollowNFTURIWithSig(uint256 profileId,string followNFTURI,uint256 nonce,uint256 deadline)'
);
bytes32 internal constant SET_DISPATCHER_WITH_SIG_TYPEHASH =
keccak256(
'SetDispatcherWithSig(uint256 profileId,address dispatcher,uint256 nonce,uint256 deadline)'
);
bytes32 internal constant SET_PROFILE_IMAGE_URI_WITH_SIG_TYPEHASH =
keccak256(
'SetProfileImageURIWithSig(uint256 profileId,string imageURI,uint256 nonce,uint256 deadline)'
);
bytes32 internal constant POST_WITH_SIG_TYPEHASH =
keccak256(
'PostWithSig(uint256 profileId,string contentURI,address collectModule,bytes collectModuleInitData,address referenceModule,bytes referenceModuleInitData,uint256 nonce,uint256 deadline)'
);
bytes32 internal constant COMMENT_WITH_SIG_TYPEHASH =
keccak256(
'CommentWithSig(uint256 profileId,string contentURI,uint256 profileIdPointed,uint256 pubIdPointed,bytes referenceModuleData,address collectModule,bytes collectModuleInitData,address referenceModule,bytes referenceModuleInitData,uint256 nonce,uint256 deadline)'
);
bytes32 internal constant MIRROR_WITH_SIG_TYPEHASH =
keccak256(
'MirrorWithSig(uint256 profileId,uint256 profileIdPointed,uint256 pubIdPointed,bytes referenceModuleData,address referenceModule,bytes referenceModuleInitData,uint256 nonce,uint256 deadline)'
);
bytes32 internal constant FOLLOW_WITH_SIG_TYPEHASH =
keccak256(
'FollowWithSig(uint256[] profileIds,bytes[] datas,uint256 nonce,uint256 deadline)'
);
bytes32 internal constant COLLECT_WITH_SIG_TYPEHASH =
keccak256(
'CollectWithSig(uint256 profileId,uint256 pubId,bytes data,uint256 nonce,uint256 deadline)'
);
mapping(address => bool) internal _profileCreatorWhitelisted; // Slot 13
mapping(address => bool) internal _followModuleWhitelisted; // Slot 14
mapping(address => bool) internal _collectModuleWhitelisted; // Slot 15
mapping(address => bool) internal _referenceModuleWhitelisted; // Slot 16
mapping(uint256 => address) internal _dispatcherByProfile;
mapping(uint256 => address) internal _dispatcherByProfile;
mapping(bytes32 => uint256) internal _profileIdByHandleHash;
mapping(uint256 => DataTypes.ProfileStruct) internal _profileById;
mapping(uint256 => mapping(uint256 => DataTypes.PublicationStruct)) internal _pubByIdByProfile;
@@ -67,6 +26,6 @@ abstract contract LensHubStorage {
mapping(address => uint256) internal _defaultProfileByAddress;
uint256 internal _profileCounter;
address internal _governance;
address internal _emergencyAdmin;
address internal _governance; // slot 23
address internal _emergencyAdmin; // slot 24
}

View File

@@ -11,20 +11,104 @@ import {IFollowModule} from '../interfaces/IFollowModule.sol';
import {ICollectModule} from '../interfaces/ICollectModule.sol';
import {IReferenceModule} from '../interfaces/IReferenceModule.sol';
// TODO: Migrate governance/admin logic here. (incl events)
// TODO: Migrate complex storage here. (incl events)
/**
* @title PublishingLogic
* @title GeneralLib
* @author Lens Protocol
*
* @notice This is the library that contains the logic for profile creation & publication.
* @notice This is the library that contains the logic for profile creation, publication,
* admin, and governance functionality.
*
* @dev The functions are external, so they are called from the hub via `delegateCall` under the hood. Furthermore,
* expected events are emitted from this library instead of from the hub to alleviate code size concerns.
* @dev The functions are external, so they are called from the hub via `delegateCall` under
* the hood. Furthermore, expected events are emitted from this library instead of from the
* hub to alleviate code size concerns.
*/
library PublishingLogic {
library GeneralLib {
uint256 constant PROTOCOL_STATE_SLOT = 12;
uint256 constant PROFILE_CREATOR_WHITELIST_MAPPING_SLOT = 13;
uint256 constant FOLLOW_MODULE_WHITELIST_MAPPING_SLOT = 14;
uint256 constant COLLECT_MODULE_WHITELIST_MAPPING_SLOT = 15;
uint256 constant REFERENCE_MODULE_WHITELIST_MAPPING_SLOT = 16;
uint256 constant GOVERNANCE_SLOT = 23;
uint256 constant EMERGENCY_ADMIN_SLOT = 24;
/**
* @notice Sets the governance address.
*
* @param newGovernance The new governance address to set.
*/
function setGovernance(address newGovernance) external {
address prevGovernance;
assembly {
prevGovernance := sload(GOVERNANCE_SLOT)
sstore(GOVERNANCE_SLOT, newGovernance)
}
emit Events.GovernanceSet(msg.sender, prevGovernance, newGovernance, block.timestamp);
}
/**
* @notice Sets the emergency admin address.
*
* @param newEmergencyAdmin The new governance address to set.
*/
function setEmergencyAdmin(address newEmergencyAdmin) external {
address prevEmergencyAdmin;
assembly {
prevEmergencyAdmin := sload(EMERGENCY_ADMIN_SLOT)
sstore(EMERGENCY_ADMIN_SLOT, newEmergencyAdmin)
}
emit Events.EmergencyAdminSet(
msg.sender,
prevEmergencyAdmin,
newEmergencyAdmin,
block.timestamp
);
}
/**
* @notice Sets the protocol state.
*
* @param newState The new protocol state to set.
*
* Note: This does NOT validate the caller, and is only to be used for initialization.
*/
function setStateSimple(DataTypes.ProtocolState newState) external {
DataTypes.ProtocolState prevState;
assembly {
prevState := sload(PROTOCOL_STATE_SLOT)
sstore(PROTOCOL_STATE_SLOT, newState)
}
emit Events.StateSet(msg.sender, prevState, newState, block.timestamp);
}
/**
* @notice Sets the protocol state and validates the caller. The emergency admin can only
* pause further (Unpaused => PublishingPaused => Paused). Whereas governance can set any
* state.
*
* @param newState The new protocol state to set.
*/
function setStateFull(DataTypes.ProtocolState newState) external {
address emergencyAdmin;
address governance;
DataTypes.ProtocolState prevState;
assembly {
emergencyAdmin := sload(EMERGENCY_ADMIN_SLOT)
governance := sload(GOVERNANCE_SLOT)
prevState := sload(PROTOCOL_STATE_SLOT)
sstore(PROTOCOL_STATE_SLOT, newState)
}
if (msg.sender == emergencyAdmin) {
if (newState == DataTypes.ProtocolState.Unpaused)
revert Errors.EmergencyAdminCannotUnpause();
if (prevState == DataTypes.ProtocolState.Paused) revert Errors.Paused();
} else if (msg.sender != governance) {
revert Errors.NotGovernanceOrEmergencyAdmin();
}
emit Events.StateSet(msg.sender, prevState, newState, block.timestamp);
}
/**
* @notice Executes the logic to create a profile with the given parameters to the given address.

View File

@@ -7,7 +7,7 @@ import {Events} from '../libraries/Events.sol';
import {Helpers} from '../libraries/Helpers.sol';
import {DataTypes} from '../libraries/DataTypes.sol';
import {Errors} from '../libraries/Errors.sol';
import {PublishingLogic} from '../libraries/PublishingLogic.sol';
import {GeneralLib} from '../libraries/GeneralLib.sol';
import {InteractionLogic} from '../libraries/InteractionLogic.sol';
import {LensNFTBase} from '../core/base/LensNFTBase.sol';
import {LensMultiState} from '../core/base/LensMultiState.sol';

View File

@@ -7,7 +7,7 @@ import {Events} from '../libraries/Events.sol';
import {Helpers} from '../libraries/Helpers.sol';
import {DataTypes} from '../libraries/DataTypes.sol';
import {Errors} from '../libraries/Errors.sol';
import {PublishingLogic} from '../libraries/PublishingLogic.sol';
import {GeneralLib} from '../libraries/GeneralLib.sol';
import {InteractionLogic} from '../libraries/InteractionLogic.sol';
import {LensNFTBase} from '../core/base/LensNFTBase.sol';
import {LensMultiState} from '../core/base/LensMultiState.sol';

View File

@@ -16,7 +16,7 @@ import {
LimitedFeeCollectModule__factory,
LimitedTimedFeeCollectModule__factory,
ModuleGlobals__factory,
PublishingLogic__factory,
GeneralLib__factory,
RevertCollectModule__factory,
TimedFeeCollectModule__factory,
TransparentUpgradeableProxy__factory,
@@ -78,10 +78,10 @@ task('full-deploy-verify', 'deploys the entire Lens Protocol with explorer verif
console.log('\n\t-- Deploying Logic Libs --');
const publishingLogic = await deployWithVerify(
new PublishingLogic__factory(deployer).deploy({ nonce: deployerNonce++ }),
const generalLib = await deployWithVerify(
new GeneralLib__factory(deployer).deploy({ nonce: deployerNonce++ }),
[],
'contracts/libraries/PublishingLogic.sol:PublishingLogic'
'contracts/libraries/GeneralLib.sol:GeneralLib'
);
const interactionLogic = await deployWithVerify(
new InteractionLogic__factory(deployer).deploy({ nonce: deployerNonce++ }),
@@ -99,7 +99,7 @@ task('full-deploy-verify', 'deploys the entire Lens Protocol with explorer verif
'contracts/libraries/MetaTxLib.sol:MetaTxLib'
);
const hubLibs = {
'contracts/libraries/PublishingLogic.sol:PublishingLogic': publishingLogic.address,
'contracts/libraries/GeneralLib.sol:GeneralLib': generalLib.address,
'contracts/libraries/InteractionLogic.sol:InteractionLogic': interactionLogic.address,
'contracts/libraries/ProfileTokenURILogic.sol:ProfileTokenURILogic':
profileTokenURILogic.address,
@@ -358,7 +358,7 @@ task('full-deploy-verify', 'deploys the entire Lens Protocol with explorer verif
const addrs = {
'lensHub proxy': lensHub.address,
'lensHub impl:': lensHubImpl.address,
'publishing logic lib': publishingLogic.address,
'publishing logic lib': generalLib.address,
'interaction logic lib': interactionLogic.address,
'profile token URI logic lib': profileTokenURILogic.address,
'follow NFT impl': followNFTImplAddress,

View File

@@ -16,7 +16,7 @@ import {
LimitedFeeCollectModule__factory,
LimitedTimedFeeCollectModule__factory,
ModuleGlobals__factory,
PublishingLogic__factory,
GeneralLib__factory,
RevertCollectModule__factory,
TimedFeeCollectModule__factory,
TransparentUpgradeableProxy__factory,
@@ -60,8 +60,8 @@ task('full-deploy', 'deploys the entire Lens Protocol').setAction(async ({}, hre
console.log('\n\t-- Deploying Logic Libs --');
const publishingLogic = await deployContract(
new PublishingLogic__factory(deployer).deploy({ nonce: deployerNonce++ })
const generalLib = await deployContract(
new GeneralLib__factory(deployer).deploy({ nonce: deployerNonce++ })
);
const interactionLogic = await deployContract(
new InteractionLogic__factory(deployer).deploy({ nonce: deployerNonce++ })
@@ -73,7 +73,7 @@ task('full-deploy', 'deploys the entire Lens Protocol').setAction(async ({}, hre
new MetaTxLib__factory(deployer).deploy({ nonce: deployerNonce++ })
);
const hubLibs = {
'contracts/libraries/PublishingLogic.sol:PublishingLogic': publishingLogic.address,
'contracts/libraries/GeneralLib.sol:GeneralLib': generalLib.address,
'contracts/libraries/InteractionLogic.sol:InteractionLogic': interactionLogic.address,
'contracts/libraries/ProfileTokenURILogic.sol:ProfileTokenURILogic':
profileTokenURILogic.address,
@@ -298,7 +298,7 @@ task('full-deploy', 'deploys the entire Lens Protocol').setAction(async ({}, hre
const addrs = {
'lensHub proxy': lensHub.address,
'lensHub impl:': lensHubImpl.address,
'publishing logic lib': publishingLogic.address,
'publishing logic lib': generalLib.address,
'interaction logic lib': interactionLogic.address,
'follow NFT impl': followNFTImplAddress,
'collect NFT impl': collectNFTImplAddress,

View File

@@ -3,7 +3,7 @@ import { hexlify, keccak256, RLP } from 'ethers/lib/utils';
import { task } from 'hardhat/config';
import {
LensHub__factory,
PublishingLogic__factory,
GeneralLib__factory,
InteractionLogic__factory,
ProfileTokenURILogic__factory,
FollowNFT__factory,
@@ -24,8 +24,8 @@ task('list-storage', '').setAction(async ({}, hre) => {
console.log('\n\t-- Deploying Logic Libs --');
const publishingLogic = await deployContract(
new PublishingLogic__factory(deployer).deploy({ nonce: deployerNonce++ })
const generalLib = await deployContract(
new GeneralLib__factory(deployer).deploy({ nonce: deployerNonce++ })
);
const interactionLogic = await deployContract(
new InteractionLogic__factory(deployer).deploy({ nonce: deployerNonce++ })
@@ -37,7 +37,7 @@ task('list-storage', '').setAction(async ({}, hre) => {
new MetaTxLib__factory(deployer).deploy({ nonce: deployerNonce++ })
);
const hubLibs = {
'contracts/libraries/PublishingLogic.sol:PublishingLogic': publishingLogic.address,
'contracts/libraries/GeneralLib.sol:GeneralLib': generalLib.address,
'contracts/libraries/InteractionLogic.sol:InteractionLogic': interactionLogic.address,
'contracts/libraries/ProfileTokenURILogic.sol:ProfileTokenURILogic':
profileTokenURILogic.address,

View File

@@ -16,7 +16,7 @@ import {
LimitedFeeCollectModule__factory,
LimitedTimedFeeCollectModule__factory,
ModuleGlobals__factory,
PublishingLogic__factory,
GeneralLib__factory,
RevertCollectModule__factory,
TimedFeeCollectModule__factory,
TransparentUpgradeableProxy__factory,
@@ -77,10 +77,10 @@ task(
console.log('\n\t-- Deploying Logic Libs --');
const publishingLogic = await deployWithVerify(
new PublishingLogic__factory(deployer).deploy({ nonce: deployerNonce++ }),
const generalLib = await deployWithVerify(
new GeneralLib__factory(deployer).deploy({ nonce: deployerNonce++ }),
[],
'contracts/libraries/PublishingLogic.sol:PublishingLogic'
'contracts/libraries/GeneralLib.sol:GeneralLib'
);
const interactionLogic = await deployWithVerify(
new InteractionLogic__factory(deployer).deploy({ nonce: deployerNonce++ }),
@@ -98,7 +98,7 @@ task(
'contracts/libraries/MetaTxLib.sol:MetaTxLib'
);
const hubLibs = {
'contracts/libraries/PublishingLogic.sol:PublishingLogic': publishingLogic.address,
'contracts/libraries/GeneralLib.sol:GeneralLib': generalLib.address,
'contracts/libraries/InteractionLogic.sol:InteractionLogic': interactionLogic.address,
'contracts/libraries/ProfileTokenURILogic.sol:ProfileTokenURILogic':
profileTokenURILogic.address,
@@ -346,7 +346,7 @@ task(
const addrs = {
'lensHub proxy': lensHub.address,
'lensHub impl:': lensHubImpl.address,
'publishing logic lib': publishingLogic.address,
'publishing logic lib': generalLib.address,
'interaction logic lib': interactionLogic.address,
'profile token URI logic lib': profileTokenURILogic.address,
'follow NFT impl': followNFTImplAddress,

View File

@@ -38,7 +38,7 @@ import {
ModuleGlobals,
ModuleGlobals__factory,
ProfileTokenURILogic__factory,
PublishingLogic__factory,
GeneralLib__factory,
MetaTxLib__factory,
RevertCollectModule,
RevertCollectModule__factory,
@@ -165,12 +165,12 @@ before(async function () {
treasuryAddress,
TREASURY_FEE_BPS
);
const publishingLogic = await new PublishingLogic__factory(deployer).deploy();
const generalLib = await new GeneralLib__factory(deployer).deploy();
const interactionLogic = await new InteractionLogic__factory(deployer).deploy();
const profileTokenURILogic = await new ProfileTokenURILogic__factory(deployer).deploy();
const metaTxLib = await new MetaTxLib__factory(deployer).deploy();
hubLibs = {
'contracts/libraries/PublishingLogic.sol:PublishingLogic': publishingLogic.address,
'contracts/libraries/GeneralLib.sol:GeneralLib': generalLib.address,
'contracts/libraries/InteractionLogic.sol:InteractionLogic': interactionLogic.address,
'contracts/libraries/ProfileTokenURILogic.sol:ProfileTokenURILogic':
profileTokenURILogic.address,