diff --git a/addresses.json b/addresses.json index faadd2b..0e15038 100644 --- a/addresses.json +++ b/addresses.json @@ -58,6 +58,7 @@ "chainId": 80001, "network": "mumbai", "LensHubProxy": "0x60Ae865ee4C725cd04353b5AAb364553f56ceF82", + "ProfileCreator": "0x6C1e1bC39b13f9E0Af9424D76De899203F47755F", "Modules": { "v1": { "collect": [ diff --git a/contracts/misc/LensV2UpgradeContract.sol b/contracts/misc/LensV2UpgradeContract.sol index d890cc7..3fd6d34 100644 --- a/contracts/misc/LensV2UpgradeContract.sol +++ b/contracts/misc/LensV2UpgradeContract.sol @@ -10,17 +10,23 @@ contract LensV2UpgradeContract is ImmutableOwnable { ProxyAdmin public immutable PROXY_ADMIN; Governance public immutable GOVERNANCE; address public immutable newImplementation; + address public immutable TREASURY; + uint16 public immutable TREASURY_FEE; constructor( address proxyAdminAddress, address governanceAddress, address owner, address lensHub, - address newImplementationAddress + address newImplementationAddress, + address treasury, + uint16 treasuryFee ) ImmutableOwnable(owner, lensHub) { PROXY_ADMIN = ProxyAdmin(proxyAdminAddress); GOVERNANCE = Governance(governanceAddress); newImplementation = newImplementationAddress; + TREASURY = treasury; + TREASURY_FEE = treasuryFee; } function executeLensV2Upgrade() external onlyOwner { @@ -31,6 +37,7 @@ contract LensV2UpgradeContract is ImmutableOwnable { function _upgrade() internal { PROXY_ADMIN.proxy_upgrade(newImplementation); + GOVERNANCE.lensHub_setTreasuryParams(TREASURY, TREASURY_FEE); GOVERNANCE.clearControllerContract(); } } diff --git a/contracts/misc/access/Governance.sol b/contracts/misc/access/Governance.sol index fbf71c5..ca0f722 100644 --- a/contracts/misc/access/Governance.sol +++ b/contracts/misc/access/Governance.sol @@ -24,6 +24,14 @@ contract Governance is ControllableByContract { LENS_HUB.setEmergencyAdmin(newEmergencyAdmin); } + function lensHub_setTreasuryParams( + address newTreasury, + uint16 newTreasuryFee + ) external onlyOwnerOrControllerContract { + LENS_HUB.setTreasury(newTreasury); + LENS_HUB.setTreasuryFee(newTreasuryFee); + } + //////////////////////////////////////////////////////// /// ONLY GOVERNANCE OWNER OR CONTROLLER CONTRACT /// //////////////////////////////////////////////////////// diff --git a/script/LensV1ChangeAdmins.s.sol b/script/LensV1ChangeAdmins.s.sol new file mode 100644 index 0000000..e6c45ab --- /dev/null +++ b/script/LensV1ChangeAdmins.s.sol @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.13; + +import {ForkManagement} from 'script/helpers/ForkManagement.sol'; +import 'forge-std/Script.sol'; +import {LensHub as LegacyLensHub} from './../lib/core-private/contracts/core/LensHub.sol'; +import {Governance} from 'contracts/misc/access/Governance.sol'; +import {LensV2UpgradeContract} from 'contracts/misc/LensV2UpgradeContract.sol'; +import {ProxyAdmin} from 'contracts/misc/access/ProxyAdmin.sol'; +import {TransparentUpgradeableProxy} from '@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol'; + +contract LensV1ChangeAdmins is Script, ForkManagement { + using stdJson for string; + + bytes32 constant ADMIN_SLOT = bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1); + + LegacyLensHub legacyLensHub; + TransparentUpgradeableProxy lensHubAsProxy; + Governance governanceContract; + address proxyAdmin; + address governance; + ProxyAdmin proxyAdminContract; + + function loadBaseAddresses() internal override { + address lensHubProxyAddress = json.readAddress(string(abi.encodePacked('.', targetEnv, '.LensHubProxy'))); + legacyLensHub = LegacyLensHub(lensHubProxyAddress); + vm.label(lensHubProxyAddress, 'LensHub'); + console.log('Legacy Lens Hub: %s', address(legacyLensHub)); + lensHubAsProxy = TransparentUpgradeableProxy(payable(lensHubProxyAddress)); + + address governanceContractAddress = json.readAddress( + string(abi.encodePacked('.', targetEnv, '.GovernanceContract')) + ); + governanceContract = Governance(governanceContractAddress); + vm.label(governanceContractAddress, 'GovernanceContract'); + console.log('Governance Contract: %s', address(governanceContract)); + + proxyAdmin = address(uint160(uint256(vm.load(lensHubProxyAddress, ADMIN_SLOT)))); + vm.label(proxyAdmin, 'ProxyAdmin'); + console.log('LensHub Current Proxy Admin: %s', proxyAdmin); + + governance = legacyLensHub.getGovernance(); + console.log('LensHub Current governance: %s', address(governance)); + + address proxyAdminContractAddress = json.readAddress( + string(abi.encodePacked('.', targetEnv, '.ProxyAdminContract')) + ); + proxyAdminContract = ProxyAdmin(proxyAdminContractAddress); + vm.label(proxyAdminContractAddress, 'ProxyAdmin'); + console.log('Proxy Admin Contract: %s', address(proxyAdminContract)); + } + + function castTransaction(address from, address to, string memory functionSignature, string memory params) internal { + string[] memory inputs = new string[](10); + inputs[0] = 'cast'; + inputs[1] = 'send'; + inputs[2] = '--rpc-url'; + inputs[3] = network; + inputs[4] = '--unlocked'; + inputs[5] = '--from'; + inputs[6] = vm.toString(from); + inputs[7] = vm.toString(to); + inputs[8] = functionSignature; + inputs[9] = params; + vm.ffi(inputs); + } + + function _changeAdmins() internal { + castTransaction(governance, address(legacyLensHub), 'setGovernance(address)', vm.toString(address(this))); + + castTransaction( + proxyAdmin, + address(lensHubAsProxy), + 'changeAdmin(address)', + vm.toString(address(proxyAdminContract)) + ); + } + + function run(string memory targetEnv_) external { + targetEnv = targetEnv_; + loadJson(); + checkNetworkParams(); + loadBaseAddresses(); + _changeAdmins(); + } +} diff --git a/script/LensV2FreshDeployment.s.sol b/script/LensV2DeployPeriphery.s.sol similarity index 76% rename from script/LensV2FreshDeployment.s.sol rename to script/LensV2DeployPeriphery.s.sol index 0aaf506..3e00d4e 100644 --- a/script/LensV2FreshDeployment.s.sol +++ b/script/LensV2DeployPeriphery.s.sol @@ -29,13 +29,15 @@ import {Types} from 'contracts/libraries/constants/Types.sol'; import {ModuleRegistry} from 'contracts/misc/ModuleRegistry.sol'; import {IModuleRegistry} from 'contracts/interfaces/IModuleRegistry.sol'; import {BaseFeeCollectModuleInitData} from 'contracts/modules/interfaces/IBaseFeeCollectModule.sol'; +import {Governance} from 'contracts/misc/access/Governance.sol'; import {ArrayHelpers} from 'test/helpers/ArrayHelpers.sol'; -contract LensV2FreshDeployment is Script, ForkManagement, ArrayHelpers { +contract LensV2DeployPeriphery is Script, ForkManagement, ArrayHelpers { using stdJson for string; - bytes32 constant ADMIN_SLOT = bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1); + string addressesFile = 'addressesV2.txt'; + string mnemonic; struct LensAccount { @@ -46,12 +48,13 @@ contract LensV2FreshDeployment is Script, ForkManagement, ArrayHelpers { LensAccount deployer; LensAccount governance; - LensAccount proxyAdmin; - LensAccount treasury; - LensAccount profileCreator; + Governance governanceContract; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + address profileCreator; + address proxyAdmin; + ModuleRegistry moduleRegistryImpl; TransparentUpgradeableProxy moduleRegistryProxy; ModuleRegistry moduleRegistry; @@ -80,6 +83,41 @@ contract LensV2FreshDeployment is Script, ForkManagement, ArrayHelpers { //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + function saveContractAddress(string memory contractName, address deployedAddress) internal { + // console.log('Saving %s (%s) into addresses under %s environment', contractName, deployedAddress, targetEnv); + string[] memory inputs = new string[](5); + inputs[0] = 'node'; + inputs[1] = 'script/helpers/saveAddress.js'; + inputs[2] = targetEnv; + inputs[3] = contractName; + inputs[4] = vm.toString(deployedAddress); + // bytes memory res = + vm.ffi(inputs); + // string memory output = abi.decode(res, (string)); + // console.log(output); + } + + function saveModule( + string memory moduleName, + address moduleAddress, + string memory lensVersion, + string memory moduleType + ) internal { + // console.log('Saving %s (%s) into addresses under %s environment', moduleName, moduleAddress, targetEnv); + string[] memory inputs = new string[](7); + inputs[0] = 'node'; + inputs[1] = 'script/helpers/saveAddress.js'; + inputs[2] = targetEnv; + inputs[3] = moduleName; + inputs[4] = vm.toString(moduleAddress); + inputs[5] = lensVersion; + inputs[6] = moduleType; + // bytes memory res = + vm.ffi(inputs); + // string memory output = abi.decode(res, (string)); + // console.log(output); + } + function loadPrivateKeys() internal { if (isEnvSet('MNEMONIC')) { mnemonic = vm.envString('MNEMONIC'); @@ -95,123 +133,59 @@ contract LensV2FreshDeployment is Script, ForkManagement, ArrayHelpers { console.log('\n- - - DEPLOYER: %s', deployer.owner); (governance.owner, governance.ownerPk) = deriveRememberKey(mnemonic, 1); console.log('\n- - - GOVERNANCE: %s', governance.owner); - (proxyAdmin.owner, proxyAdmin.ownerPk) = deriveRememberKey(mnemonic, 2); - console.log('\n- - - PROXYADMIN: %s', proxyAdmin.owner); - (treasury.owner, treasury.ownerPk) = deriveRememberKey(mnemonic, 3); - console.log('\n- - - TREASURY: %s', treasury.owner); - profileCreator.owner = 0x6C1e1bC39b13f9E0Af9424D76De899203F47755F; - console.log('\n- - - PROFILE CREATOR: %s', profileCreator.owner); } - function run(string memory targetEnv_) external { - targetEnv = targetEnv_; - loadJson(); - checkNetworkParams(); - loadPrivateKeys(); - deploy(); - _writeBackendEnvFile(); - _interact(); + function loadBaseAddresses() internal override { + address governanceContractAdmin = json.readAddress( + string(abi.encodePacked('.', targetEnv, '.GovernanceContractAdmin')) + ); + if (governance.owner != governanceContractAdmin) { + console.log( + 'Mock Governance %s != Governance contract admin %s', + governance.owner, + governanceContractAdmin + ); + revert(); + } + + profileCreator = json.readAddress(string(abi.encodePacked('.', targetEnv, '.ProfileCreator'))); + vm.label(profileCreator, 'ProfileCreator'); + console.log('ProfileCreator: %s', profileCreator); + + proxyAdmin = json.readAddress(string(abi.encodePacked('.', targetEnv, '.ProxyAdminContractAdmin'))); + vm.label(proxyAdmin, 'ProxyAdminContractAdmin'); + console.log('ProxyAdminContractAdmin: %s', proxyAdmin); + + hub = ILensHub(json.readAddress(string(abi.encodePacked('.', targetEnv, '.LensHubProxy')))); + vm.label(address(hub), 'LensHub'); + console.log('Lens Hub Proxy: %s', address(hub)); + + handles = ILensHandles(json.readAddress(string(abi.encodePacked('.', targetEnv, '.LensHandles')))); + vm.label(address(handles), 'LensHandles'); + console.log('Lens Handles: %s', address(handles)); + + tokenHandleRegistry = ITokenHandleRegistry( + json.readAddress(string(abi.encodePacked('.', targetEnv, '.TokenHandleRegistry'))) + ); + vm.label(address(tokenHandleRegistry), 'TokenHandleRegistry'); + console.log('Token Handle Registry: %s', address(tokenHandleRegistry)); + + moduleRegistry = ModuleRegistry(json.readAddress(string(abi.encodePacked('.', targetEnv, '.ModuleRegistry')))); + vm.label(address(moduleRegistry), 'ModuleRegistry'); + console.log('Module Registry: %s', address(moduleRegistry)); + + governanceContract = Governance( + json.readAddress(string(abi.encodePacked('.', targetEnv, '.GovernanceContract'))) + ); + vm.label(address(governanceContract), 'GovernanceContract'); + console.log('Governance Contract: %s', address(governanceContract)); } function deploy() internal { - string memory addressesFile = 'addressesV2.txt'; - vm.startBroadcast(deployer.ownerPk); - moduleRegistryImpl = new ModuleRegistry(); - console.log('\n+ + + ModuleRegistryIpml: %s', address(moduleRegistryImpl)); - vm.writeLine(addressesFile, string.concat('ModuleRegistryIpml: ', vm.toString(address(moduleRegistryImpl)))); - moduleRegistryProxy = new TransparentUpgradeableProxy({ - _logic: address(moduleRegistryImpl), - admin_: proxyAdmin.owner, - _data: '' - }); - console.log('\n+ + + ModuleRegistry: %s', address(moduleRegistryProxy)); - vm.writeLine(addressesFile, string.concat('ModuleRegistry: ', vm.toString(address(moduleRegistryProxy)))); - moduleRegistry = ModuleRegistry(address(moduleRegistryProxy)); - - uint256 currentDeployerNonce = vm.getNonce(deployer.owner); - /** - * FollowNFT (currentDeployerNonce) - * LensHubInitializable aka LensHubImpl (currentDeployerNonce + 1) - * TransparentUpgradeableProxy aka LensHubProxy (currentDeployerNonce + 2) - */ - uint256 lensHubProxyDeploymentNonce = currentDeployerNonce + 2; - address expectedLensHubProxyAddress = computeCreateAddress(deployer.owner, lensHubProxyDeploymentNonce); - - followNFT = new FollowNFT(expectedLensHubProxyAddress); - console.log('\n+ + + FollowNFT: %s', address(followNFT)); - vm.writeLine(addressesFile, string.concat('FollowNFT: ', vm.toString(address(followNFT)))); - - lensHubImpl = new LensHubInitializable({ - followNFTImpl: address(followNFT), - collectNFTImpl: address(0), // No needed on a fresh V2 deployment, no publications will have legacy collect. - moduleRegistry: address(moduleRegistry), - tokenGuardianCooldown: 5 minutes, - migrationParams: Types.MigrationParams({ - lensHandlesAddress: address(0), - tokenHandleRegistryAddress: address(0), - legacyFeeFollowModule: address(0), - legacyProfileFollowModule: address(0), - newFeeFollowModule: address(0), - migrationAdmin: address(0) - }) // No needed on a fresh V2 deployment, no migration needed. - }); - console.log('\n+ + + LensHubImpl: %s', address(lensHubImpl)); - vm.writeLine(addressesFile, string.concat('LensHubImpl: ', vm.toString(address(lensHubImpl)))); - - hubProxy = new TransparentUpgradeableProxy({ - _logic: address(lensHubImpl), - admin_: proxyAdmin.owner, - _data: abi.encodeWithSelector( - LensHubInitializable.initialize.selector, - 'Lens Protocol Profiles', // Name - 'LPP', // Symbol - governance.owner - ) - }); - hub = ILensHub(address(hubProxy)); - console.log('\n+ + + LensHub: %s', address(hub)); - vm.writeLine(addressesFile, string.concat('LensHub: ', vm.toString(address(hub)))); - - handlesImpl = new LensHandles({ - owner: governance.owner, - lensHub: address(hub), - tokenGuardianCooldown: 5 minutes - }); - console.log('\n+ + + LensHandlesImpl: %s', address(handlesImpl)); - vm.writeLine(addressesFile, string.concat('LensHandlesImpl: ', vm.toString(address(handlesImpl)))); - - handlesProxy = new TransparentUpgradeableProxy({ - _logic: address(handlesImpl), - admin_: proxyAdmin.owner, - _data: '' - }); - console.log('\n+ + + LensHandles: %s', address(handlesProxy)); - vm.writeLine(addressesFile, string.concat('LensHandles: ', vm.toString(address(handlesProxy)))); - handles = ILensHandles(address(handlesProxy)); - - tokenHandleRegistryImpl = new TokenHandleRegistry({lensHub: address(hub), lensHandles: address(handles)}); - console.log('\n+ + + TokenHandleRegistryImpl: %s', address(tokenHandleRegistryImpl)); - vm.writeLine( - addressesFile, - string.concat('TokenHandleRegistryImpl: ', vm.toString(address(tokenHandleRegistryImpl))) - ); - - tokenHandleRegistryProxy = new TransparentUpgradeableProxy({ - _logic: address(tokenHandleRegistryImpl), - admin_: proxyAdmin.owner, - _data: '' - }); - console.log('\n+ + + TokenHandleRegistry: %s', address(tokenHandleRegistryProxy)); - vm.writeLine( - addressesFile, - string.concat('TokenHandleRegistry: ', vm.toString(address(tokenHandleRegistryProxy))) - ); - tokenHandleRegistry = ITokenHandleRegistry(address(tokenHandleRegistryProxy)); - profileCreationProxy = new ProfileCreationProxy({ - owner: profileCreator.owner, + owner: profileCreator, hub: address(hub), lensHandles: address(handles), tokenHandleRegistry: address(tokenHandleRegistry) @@ -221,8 +195,10 @@ contract LensV2FreshDeployment is Script, ForkManagement, ArrayHelpers { addressesFile, string.concat('ProfileCreationProxy: ', vm.toString(address(profileCreationProxy))) ); + vm.label(address(profileCreationProxy), 'ProfileCreationProxy'); + saveContractAddress('ProfileCreationProxy', address(profileCreationProxy)); - currentDeployerNonce = vm.getNonce(deployer.owner); + uint256 currentDeployerNonce = vm.getNonce(deployer.owner); /** * CollectNFT (currentDeployerNonce) * CollectPublicationAction aka CollectPublicationActionImpl (currentDeployerNonce + 1) @@ -237,6 +213,8 @@ contract LensV2FreshDeployment is Script, ForkManagement, ArrayHelpers { collectNFT = new CollectNFT({hub: address(hub), actionModule: expectedCollectPublicationActionProxyAddress}); console.log('\n+ + + CollectNFT: %s', address(collectNFT)); vm.writeLine(addressesFile, string.concat('CollectNFT: ', vm.toString(address(collectNFT)))); + vm.label(address(collectNFT), 'CollectNFT'); + saveContractAddress('CollectNFT', address(collectNFT)); collectPublicationActionImpl = new CollectPublicationAction({ hub: address(hub), @@ -247,10 +225,12 @@ contract LensV2FreshDeployment is Script, ForkManagement, ArrayHelpers { addressesFile, string.concat('CollectPublicationActionImpl: ', vm.toString(address(collectPublicationActionImpl))) ); + vm.label(address(collectPublicationActionImpl), 'CollectPublicationActionImpl'); + saveContractAddress('CollectPublicationActionImpl', address(collectPublicationActionImpl)); collectPublicationActionProxy = new TransparentUpgradeableProxy({ _logic: address(collectPublicationActionImpl), - admin_: proxyAdmin.owner, + admin_: proxyAdmin, _data: '' }); console.log('\n+ + + CollectPublicationActionProxy: %s', address(collectPublicationActionProxy)); @@ -258,6 +238,9 @@ contract LensV2FreshDeployment is Script, ForkManagement, ArrayHelpers { addressesFile, string.concat('CollectPublicationActionProxy: ', vm.toString(address(collectPublicationActionProxy))) ); + vm.label(address(collectPublicationActionProxy), 'CollectPublicationAction'); + saveModule('CollectPublicationAction', address(collectPublicationActionProxy), 'v2', 'act'); + collectPublicationAction = CollectPublicationAction(address(collectPublicationActionProxy)); simpleFeeCollectModule = new SimpleFeeCollectModule({ @@ -270,6 +253,8 @@ contract LensV2FreshDeployment is Script, ForkManagement, ArrayHelpers { addressesFile, string.concat('SimpleFeeCollectModule: ', vm.toString(address(simpleFeeCollectModule))) ); + vm.label(address(simpleFeeCollectModule), 'SimpleFeeCollectModule'); + saveModule('SimpleFeeCollectModule', address(simpleFeeCollectModule), 'v2', 'collect'); multirecipientFeeCollectModule = new MultirecipientFeeCollectModule({ hub: address(hub), @@ -281,14 +266,20 @@ contract LensV2FreshDeployment is Script, ForkManagement, ArrayHelpers { addressesFile, string.concat('MultirecipientFeeCollectModule: ', vm.toString(address(multirecipientFeeCollectModule))) ); + vm.label(address(multirecipientFeeCollectModule), 'MultirecipientFeeCollectModule'); + saveModule('MultirecipientFeeCollectModule', address(multirecipientFeeCollectModule), 'v2', 'collect'); feeFollowModule = new FeeFollowModule({hub: address(hub), moduleRegistry: address(moduleRegistry)}); console.log('\n+ + + FeeFollowModule: %s', address(feeFollowModule)); vm.writeLine(addressesFile, string.concat('FeeFollowModule: ', vm.toString(address(feeFollowModule)))); + vm.label(address(feeFollowModule), 'FeeFollowModule'); + saveModule('FeeFollowModule', address(feeFollowModule), 'v2', 'follow'); revertFollowModule = new RevertFollowModule(); console.log('\n+ + + RevertFollowModule: %s', address(revertFollowModule)); vm.writeLine(addressesFile, string.concat('RevertFollowModule: ', vm.toString(address(revertFollowModule)))); + vm.label(address(revertFollowModule), 'RevertFollowModule'); + saveModule('RevertFollowModule', address(revertFollowModule), 'v2', 'follow'); degreesOfSeparationReferenceModule = new DegreesOfSeparationReferenceModule({hub: address(hub)}); console.log('\n+ + + DegreesOfSeparationReferenceModule: %s', address(degreesOfSeparationReferenceModule)); @@ -299,6 +290,13 @@ contract LensV2FreshDeployment is Script, ForkManagement, ArrayHelpers { vm.toString(address(degreesOfSeparationReferenceModule)) ) ); + vm.label(address(degreesOfSeparationReferenceModule), 'DegreesOfSeparationReferenceModule'); + saveModule( + 'DegreesOfSeparationReferenceModule', + address(degreesOfSeparationReferenceModule), + 'v2', + 'reference' + ); followerOnlyReferenceModule = new FollowerOnlyReferenceModule({hub: address(hub)}); console.log('\n+ + + FollowerOnlyReferenceModule: %s', address(followerOnlyReferenceModule)); @@ -306,8 +304,10 @@ contract LensV2FreshDeployment is Script, ForkManagement, ArrayHelpers { addressesFile, string.concat('FollowerOnlyReferenceModule: ', vm.toString(address(followerOnlyReferenceModule))) ); + vm.label(address(followerOnlyReferenceModule), 'FollowerOnlyReferenceModule'); + saveModule('FollowerOnlyReferenceModule', address(followerOnlyReferenceModule), 'v2', 'reference'); - // NOTE: TokenGatedReferenceModule temporarily removed from the deployment + // TODO: TokenGatedReferenceModule temporarily removed from the deployment // tokenGatedReferenceModule = new TokenGatedReferenceModule({hub: address(hub)}); // console.log('\n+ + + TokenGatedReferenceModule: %s', address(tokenGatedReferenceModule)); // vm.writeLine( @@ -315,16 +315,25 @@ contract LensV2FreshDeployment is Script, ForkManagement, ArrayHelpers { // string.concat('TokenGatedReferenceModule: ', vm.toString(address(tokenGatedReferenceModule))) // ); - vm.writeLine( - addressesFile, - string.concat('FollowerOnlyReferenceModule: ', vm.toString(address(followerOnlyReferenceModule))) - ); - vm.stopBroadcast(); + } - // This can potentially be moved to a `setUp` function after the `deploy` one. + function _governanceActions() internal { vm.startBroadcast(governance.ownerPk); + governanceContract.lensHub_whitelistProfileCreator(address(profileCreationProxy), true); + console.log('\n* * * Profile creator proxy %s registered as profile creator', address(profileCreationProxy)); + + hub.setState(Types.ProtocolState.Unpaused); + console.log('\n* * * Protocol unpaused'); + + vm.stopBroadcast(); + } + + function _registerCurrencies() internal { + vm.startBroadcast(deployer.ownerPk); + + // TODO: Get the currency addresses from the addresses.json moduleRegistry.registerErc20Currency(address(0x2058A9D7613eEE744279e3856Ef0eAda5FCbaA7e)); console.log('\n* * * USDC registered as currency'); vm.writeLine( @@ -352,9 +361,11 @@ contract LensV2FreshDeployment is Script, ForkManagement, ArrayHelpers { addressesFile, string.concat('WMATIC: ', vm.toString(address(0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889))) ); + vm.stopBroadcast(); + } - hub.whitelistProfileCreator(address(profileCreationProxy), true); - console.log('\n* * * Profile creator proxy registered as profile creator'); + function _registerModules() internal { + vm.startBroadcast(deployer.ownerPk); // Follow modules moduleRegistry.registerModule(address(feeFollowModule), uint256(IModuleRegistry.ModuleType.FOLLOW_MODULE)); @@ -389,23 +400,22 @@ contract LensV2FreshDeployment is Script, ForkManagement, ArrayHelpers { collectPublicationAction.registerCollectModule(address(multirecipientFeeCollectModule)); console.log('\n* * * MultirecipientFeeCollectModule registered as collect module'); - hub.setState(Types.ProtocolState.Unpaused); - console.log('\n* * * Protocol unpaused'); - vm.stopBroadcast(); } function _interact() internal { - vm.broadcast(deployer.ownerPk); + vm.startBroadcast(deployer.ownerPk); ProfileCreationProxy temporarilyCreationProxy = new ProfileCreationProxy({ owner: deployer.owner, hub: address(hub), lensHandles: address(handles), tokenHandleRegistry: address(tokenHandleRegistry) }); + vm.stopBroadcast(); - vm.broadcast(governance.ownerPk); - hub.whitelistProfileCreator(address(temporarilyCreationProxy), true); + vm.startBroadcast(governance.ownerPk); + governanceContract.lensHub_whitelistProfileCreator(address(temporarilyCreationProxy), true); + vm.stopBroadcast(); vm.startBroadcast(deployer.ownerPk); @@ -565,8 +575,9 @@ contract LensV2FreshDeployment is Script, ForkManagement, ArrayHelpers { vm.stopBroadcast(); - vm.broadcast(governance.ownerPk); - hub.whitelistProfileCreator(address(temporarilyCreationProxy), false); + vm.startBroadcast(governance.ownerPk); + governanceContract.lensHub_whitelistProfileCreator(address(temporarilyCreationProxy), false); + vm.stopBroadcast(); } function _writeBackendEnvFile() internal { @@ -617,4 +628,15 @@ contract LensV2FreshDeployment is Script, ForkManagement, ArrayHelpers { ) ); } + + function run(string memory targetEnv_) external { + targetEnv = targetEnv_; + loadJson(); + checkNetworkParams(); + loadPrivateKeys(); + loadBaseAddresses(); + deploy(); + _writeBackendEnvFile(); + _interact(); + } } diff --git a/script/LensV2UpgradeDeployment.s.sol b/script/LensV2UpgradeDeployment.s.sol index 3418347..d6cf4c4 100644 --- a/script/LensV2UpgradeDeployment.s.sol +++ b/script/LensV2UpgradeDeployment.s.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.13; import {ForkManagement} from 'script/helpers/ForkManagement.sol'; import 'forge-std/Script.sol'; import {LensHub as LegacyLensHub} from './../lib/core-private/contracts/core/LensHub.sol'; +import {ModuleGlobals} from './../lib/core-private/contracts/core/modules/ModuleGlobals.sol'; import {LensHubInitializable} from 'contracts/misc/LensHubInitializable.sol'; import {LensV2UpgradeContract} from 'contracts/misc/LensV2UpgradeContract.sol'; import {FollowNFT} from 'contracts/FollowNFT.sol'; @@ -44,6 +45,8 @@ contract LensV2UpgradeDeployment is Script, ForkManagement, ArrayHelpers { address legacyLensHubImpl; address lensHubV2Impl; + ModuleGlobals moduleGlobals; + address followNFTImpl; address legacyCollectNFTImpl; address lensHandlesImpl; @@ -59,12 +62,16 @@ contract LensV2UpgradeDeployment is Script, ForkManagement, ArrayHelpers { LensAccount _deployer; LensAccount _proxyAdmin; LensAccount _governance; + LensAccount _treasury; + address treasury; address governance; address proxyAdmin; address migrationAdmin; address lensHandlesOwner; + uint16 treasuryFee; + ProxyAdmin proxyAdminContract; function loadBaseAddresses() internal override { @@ -77,6 +84,10 @@ contract LensV2UpgradeDeployment is Script, ForkManagement, ArrayHelpers { vm.label(legacyLensHubImpl, 'LensHubImplementation'); console.log('Legacy Lens Hub Impl: %s', address(legacyLensHubImpl)); + moduleGlobals = ModuleGlobals(json.readAddress(string(abi.encodePacked('.', targetEnv, '.ModuleGlobals')))); + vm.label(address(moduleGlobals), 'ModuleGlobals'); + console.log('ModuleGlobals: %s', address(moduleGlobals)); + Module[] memory followModules = abi.decode( vm.parseJson(json, string(abi.encodePacked('.', targetEnv, '.Modules.v1.follow'))), (Module[]) @@ -104,6 +115,12 @@ contract LensV2UpgradeDeployment is Script, ForkManagement, ArrayHelpers { proxyAdmin = address(uint160(uint256(vm.load(lensHub, ADMIN_SLOT)))); console.log('Real ProxyAdmin: %s', proxyAdmin); + + treasury = moduleGlobals.getTreasury(); + console.log('Real Treasury: %s', treasury); + + treasuryFee = moduleGlobals.getTreasuryFee(); + console.log('Real Treasury Fee: %s', treasuryFee); } else { console.log('Using governance and proxy admin from test mnemonic:'); @@ -114,6 +131,13 @@ contract LensV2UpgradeDeployment is Script, ForkManagement, ArrayHelpers { (_proxyAdmin.owner, _proxyAdmin.ownerPk) = deriveRememberKey(mnemonic, 2); console.log('\tMock ProxyAdmin: %s', _proxyAdmin.owner); proxyAdmin = _proxyAdmin.owner; + + (_treasury.owner, _treasury.ownerPk) = deriveRememberKey(mnemonic, 3); + console.log('\tMock Treasury: %s', _treasury.owner); + treasury = _treasury.owner; + + treasuryFee = 50; + console.log('\tMock Treasury Fee: %s', treasuryFee); } console.log('\n'); @@ -121,6 +145,11 @@ contract LensV2UpgradeDeployment is Script, ForkManagement, ArrayHelpers { vm.label(governance, 'Governance'); + vm.label(treasury, 'Treasury'); + + saveContractAddress('Treasury', treasury); + saveValue('TreasuryFee', vm.toString(treasuryFee)); + migrationAdmin = proxyAdmin; // TODO: change this to the real migration admin // json.readAddress(string(abi.encodePacked('.', targetEnv, '.MigrationAdmin'))); @@ -179,6 +208,20 @@ contract LensV2UpgradeDeployment is Script, ForkManagement, ArrayHelpers { // console.log(output); } + function saveValue(string memory contractName, string memory str) internal { + // console.log('Saving %s (%s) into addresses under %s environment', contractName, deployedAddress, targetEnv); + string[] memory inputs = new string[](5); + inputs[0] = 'node'; + inputs[1] = 'script/helpers/saveAddress.js'; + inputs[2] = targetEnv; + inputs[3] = contractName; + inputs[4] = str; + // bytes memory res = + vm.ffi(inputs); + // string memory output = abi.decode(res, (string)); + // console.log(output); + } + function deploy() internal { string memory addressesFile = 'addressesV2.txt'; @@ -229,7 +272,7 @@ contract LensV2UpgradeDeployment is Script, ForkManagement, ArrayHelpers { console.log('PROFILE_GUARDIAN_COOLDOWN: %s', PROFILE_GUARDIAN_COOLDOWN); - // Deploy new FeeFollowModule(hub, moduleGlobals) + // Deploy new FeeFollowModule(hub, moduleRegistry) feeFollowModule = address(new FeeFollowModule(lensHub, moduleRegistry)); vm.writeLine(addressesFile, string.concat('FeeFollowModule: ', vm.toString(feeFollowModule))); saveContractAddress('FeeFollowModule', feeFollowModule); @@ -308,7 +351,9 @@ contract LensV2UpgradeDeployment is Script, ForkManagement, ArrayHelpers { governanceAddress: address(governanceContract), owner: governance, lensHub: address(legacyLensHub), - newImplementationAddress: lensHubV2Impl + newImplementationAddress: lensHubV2Impl, + treasury: treasury, + treasuryFee: treasuryFee }) ); @@ -321,6 +366,8 @@ contract LensV2UpgradeDeployment is Script, ForkManagement, ArrayHelpers { console.log('\t"%s"', governance); console.log('\t"%s"', address(legacyLensHub)); console.log('\t"%s"', lensHubV2Impl); + console.log('\t"%s"', treasury); + console.log('\t"%s"', treasuryFee); console.log(']'); console.log('\n'); diff --git a/script/helpers/saveAddress.js b/script/helpers/saveAddress.js index 708b8ba..6ea29d5 100644 --- a/script/helpers/saveAddress.js +++ b/script/helpers/saveAddress.js @@ -4,8 +4,46 @@ const fs = require('fs'); const addressesPath = '../../addresses.json'; const addresses = require(path.join(__dirname, addressesPath)); -const [targetEnv, contract, address] = process.argv.slice(2); -addresses[targetEnv][contract] = address; -fs.writeFileSync(path.join(__dirname, addressesPath), JSON.stringify(addresses, null, 2) + '\n'); -console.log('Updated `addresses.json`'); +// If no arguments are passed - fail +if (process.argv.length < 5) { + console.error('Usage: node saveAddress.js
'); + process.exit(1); +} + +// If 3 arguments are passed - save the contract address +if (process.argv.length === 5) { + const [targetEnv, contract, address] = process.argv.slice(2); + addresses[targetEnv][contract] = address; + + fs.writeFileSync(path.join(__dirname, addressesPath), JSON.stringify(addresses, null, 2) + '\n'); + console.log('Updated `addresses.json`'); + process.exit(0); +} + +// If 5 arguments are passed - save the module address in modules +if (process.argv.length === 7) { + const [targetEnv, moduleName, moduleAddress, lensVersion, moduleType] = process.argv.slice(2); + if (addresses[targetEnv]['Modules'][lensVersion][moduleType] === undefined) { + addresses[targetEnv]['Modules'][lensVersion][moduleType] = []; + } + + // Check if the module with a same name is already in the list + const moduleIndex = addresses[targetEnv]['Modules'][lensVersion][moduleType].findIndex( + (module) => module.name === moduleName + ); + + if (moduleIndex === -1) { + addresses[targetEnv]['Modules'][lensVersion][moduleType].push({ + name: moduleName, + addy: moduleAddress, + }); + } else { + // Get the module object from the list by index and change the addy: + addresses[targetEnv]['Modules'][lensVersion][moduleType][moduleIndex].addy = moduleAddress; + } + + fs.writeFileSync(path.join(__dirname, addressesPath), JSON.stringify(addresses, null, 2) + '\n'); + console.log('Updated `addresses.json`'); + process.exit(0); +} diff --git a/script/run.sh b/script/run.sh index 0803ff6..c1a1580 100644 --- a/script/run.sh +++ b/script/run.sh @@ -4,6 +4,7 @@ set -e SCRIPT_NAME=$1 TARGET=$2 +CONFIRMATION_OVERRIDE=$3 if [[ "$TARGET" == "" ]] then @@ -27,7 +28,12 @@ echo "$CALLDATA" forge script script/$SCRIPT_NAME.s.sol:$SCRIPT_NAME -s $CALLDATA --rpc-url $NETWORK -vv --skip test --ffi -read -p "Please verify the data and confirm the interactions logs (y/n):" CONFIRMATION +if [[ "$CONFIRMATION_OVERRIDE" == "y" || "$CONFIRMATION_OVERRIDE" == "Y" || "$CONFIRMATION_OVERRIDE" == "n" || "$CONFIRMATION_OVERRIDE" == "N" ]] + then + CONFIRMATION="$CONFIRMATION_OVERRIDE" + else + read -p "Please verify the data and confirm the interactions logs (y/n):" CONFIRMATION +fi if [[ "$CONFIRMATION" == "y" || "$CONFIRMATION" == "Y" ]] then diff --git a/test/fork/UpgradeForkTest.t.sol b/test/fork/UpgradeForkTest.t.sol index d54ed1a..b7f2c3c 100644 --- a/test/fork/UpgradeForkTest.t.sol +++ b/test/fork/UpgradeForkTest.t.sol @@ -382,7 +382,9 @@ contract UpgradeForkTest is BaseTest { governanceAddress: address(governanceContract), owner: governanceMultisig, lensHub: address(hub), - newImplementationAddress: address(hubImpl) + newImplementationAddress: address(hubImpl), + treasury: address(0), // TODO: Do we need to fill this in with previous values? + treasuryFee: 0 // TODO: Do we need to fill this in with previous values? }); vm.label(address(lensV2UpgradeContract), 'LensV2UpgradeContract');