diff --git a/contracts/core/LensHub.sol b/contracts/core/LensHub.sol index fe13300..b040c89 100644 --- a/contracts/core/LensHub.sol +++ b/contracts/core/LensHub.sol @@ -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; } } diff --git a/contracts/core/base/LensMultiState.sol b/contracts/core/base/LensMultiState.sol index e58f8f0..b55e6d0 100644 --- a/contracts/core/base/LensMultiState.sol +++ b/contracts/core/base/LensMultiState.sol @@ -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) { diff --git a/contracts/core/storage/LensHubStorage.sol b/contracts/core/storage/LensHubStorage.sol index ba02d32..8b560e4 100644 --- a/contracts/core/storage/LensHubStorage.sol +++ b/contracts/core/storage/LensHubStorage.sol @@ -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 } diff --git a/contracts/libraries/PublishingLogic.sol b/contracts/libraries/GeneralLib.sol similarity index 83% rename from contracts/libraries/PublishingLogic.sol rename to contracts/libraries/GeneralLib.sol index 048a02c..1656ebd 100644 --- a/contracts/libraries/PublishingLogic.sol +++ b/contracts/libraries/GeneralLib.sol @@ -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. diff --git a/contracts/mocks/MockLensHubV2.sol b/contracts/mocks/MockLensHubV2.sol index 7ba7a3e..88961f2 100644 --- a/contracts/mocks/MockLensHubV2.sol +++ b/contracts/mocks/MockLensHubV2.sol @@ -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'; diff --git a/contracts/mocks/MockLensHubV2BadRevision.sol b/contracts/mocks/MockLensHubV2BadRevision.sol index a997464..a385bc2 100644 --- a/contracts/mocks/MockLensHubV2BadRevision.sol +++ b/contracts/mocks/MockLensHubV2BadRevision.sol @@ -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'; diff --git a/tasks/full-deploy-verify.ts b/tasks/full-deploy-verify.ts index 067870a..3239ec8 100644 --- a/tasks/full-deploy-verify.ts +++ b/tasks/full-deploy-verify.ts @@ -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, diff --git a/tasks/full-deploy.ts b/tasks/full-deploy.ts index c92f547..d078439 100644 --- a/tasks/full-deploy.ts +++ b/tasks/full-deploy.ts @@ -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, diff --git a/tasks/list-storage.ts b/tasks/list-storage.ts index f8660fe..2140cb2 100644 --- a/tasks/list-storage.ts +++ b/tasks/list-storage.ts @@ -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, diff --git a/tasks/testnet-full-deploy-verify.ts b/tasks/testnet-full-deploy-verify.ts index 340760e..70b797b 100644 --- a/tasks/testnet-full-deploy-verify.ts +++ b/tasks/testnet-full-deploy-verify.ts @@ -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, diff --git a/test/__setup.spec.ts b/test/__setup.spec.ts index 19015c7..c799b95 100644 --- a/test/__setup.spec.ts +++ b/test/__setup.spec.ts @@ -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,