// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import {ForkManagement} from 'script/helpers/ForkManagement.sol'; import 'forge-std/Script.sol'; import {LibString} from 'solady/utils/LibString.sol'; import {FollowNFT} from 'contracts/FollowNFT.sol'; import {LensHubInitializable} from 'contracts/misc/LensHubInitializable.sol'; import {Types} from 'contracts/libraries/constants/Types.sol'; import {Governance} from 'contracts/misc/access/Governance.sol'; import {LensHandles} from 'contracts/namespaces/LensHandles.sol'; contract DeployCore is Script, ForkManagement { using stdJson for string; struct LensAccount { uint256 ownerPk; address owner; uint256 profileId; } LensAccount _deployer; string mnemonic; uint256 internal PROFILE_GUARDIAN_COOLDOWN; uint256 internal HANDLE_GUARDIAN_COOLDOWN; address lensHub; address legacyCollectNFTImpl; address followNFTImpl; address moduleRegistry; address lensHandlesAddress; address tokenHandleRegistryAddress; address legacyFeeFollowModule; address legacyProfileFollowModule; address newFeeFollowModule; address lensHandlesOwner; address lensHandlesImpl; address governanceContract; address governanceAdmin; address lensHubV2Impl; string addressesFile = 'addressesV2.txt'; // TODO: Use from test/ContractAddresses struct Module { address addy; string name; } // TODO: Move this somewhere common (also in UpgradeForkTest) function findModuleHelper( Module[] memory modules, string memory moduleNameToFind ) internal pure returns (Module memory) { for (uint256 i = 0; i < modules.length; i++) { if (LibString.eq(modules[i].name, moduleNameToFind)) { return modules[i]; } } revert('Module not found'); } 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 loadPrivateKeys() internal { if (isEnvSet('MNEMONIC')) { mnemonic = vm.envString('MNEMONIC'); } if (bytes(mnemonic).length == 0) { revert('Missing mnemonic'); } console.log('\n'); (_deployer.owner, _deployer.ownerPk) = deriveRememberKey(mnemonic, 0); console.logBytes32(bytes32(_deployer.ownerPk)); console.log('Deployer address: %s', address(_deployer.owner)); console.log('\n'); console.log('Current block:', block.number); } function loadBaseAddresses() internal override { lensHub = json.readAddress(string(abi.encodePacked('.', targetEnv, '.LensHub'))); vm.label(lensHub, 'LensHub'); console.log('Lens Hub Proxy: %s', lensHub); legacyCollectNFTImpl = json.readAddress(string(abi.encodePacked('.', targetEnv, '.LegacyCollectNFTImpl'))); vm.label(legacyCollectNFTImpl, 'LegacyCollectNFTImpl'); console.log('LegacyCollectNFTImpl: %s', legacyCollectNFTImpl); moduleRegistry = json.readAddress(string(abi.encodePacked('.', targetEnv, '.ModuleRegistry'))); vm.label(moduleRegistry, 'ModuleRegistry'); console.log('ModuleRegistry: %s', moduleRegistry); PROFILE_GUARDIAN_COOLDOWN = json.readUint( string(abi.encodePacked('.', targetEnv, '.LensProfilesGuardianTimelock')) ); console.log('PROFILE_GUARDIAN_COOLDOWN: %s', PROFILE_GUARDIAN_COOLDOWN); HANDLE_GUARDIAN_COOLDOWN = json.readUint( string(abi.encodePacked('.', targetEnv, '.LensHandlesGuardianTimelock')) ); console.log('HANDLE_GUARDIAN_COOLDOWN: %s', HANDLE_GUARDIAN_COOLDOWN); lensHandlesAddress = json.readAddress(string(abi.encodePacked('.', targetEnv, '.LensHandles'))); tokenHandleRegistryAddress = json.readAddress(string(abi.encodePacked('.', targetEnv, '.TokenHandleRegistry'))); Module[] memory followModules = abi.decode( vm.parseJson(json, string(abi.encodePacked('.', targetEnv, '.Modules.v1.follow'))), (Module[]) ); legacyFeeFollowModule = findModuleHelper(followModules, 'FeeFollowModule').addy; vm.label(legacyFeeFollowModule, 'LegacyFeeFollowModule'); console.log('Legacy Fee Follow Module: %s', legacyFeeFollowModule); legacyProfileFollowModule = findModuleHelper(followModules, 'ProfileFollowModule').addy; vm.label(legacyProfileFollowModule, 'LegacyProfileFollowModule'); console.log('Legacy Profile Follow Module: %s', legacyProfileFollowModule); followModules = abi.decode( vm.parseJson(json, string(abi.encodePacked('.', targetEnv, '.Modules.v2.follow'))), (Module[]) ); newFeeFollowModule = findModuleHelper(followModules, 'FeeFollowModule').addy; vm.label(newFeeFollowModule, 'NewFeeFollowModule'); console.log('New Fee Follow Module: %s', newFeeFollowModule); governanceContract = LensHubInitializable(lensHub).getGovernance(); governanceAdmin = Governance(governanceContract).owner(); lensHandlesOwner = governanceAdmin; vm.label(lensHandlesOwner, 'LensHandlesOwner'); console.log('LensHandlesOwner: %s', lensHandlesOwner); } function deploy() internal { if (lensHub == address(0)) { console.log('LensHub not set'); revert('LensHub not set'); } if (lensHandlesOwner == address(0)) { console.log('lensHandlesOwner not set'); revert('lensHandlesOwner not set'); } if (HANDLE_GUARDIAN_COOLDOWN == 0) { console.log('HANDLE_GUARDIAN_COOLDOWN not set'); revert('HANDLE_GUARDIAN_COOLDOWN not set'); } vm.startBroadcast(_deployer.ownerPk); // Deploy FollowNFTImpl(hub) followNFTImpl = address(new FollowNFT(lensHub)); // Deploy LensHandles(owner, hub) implementation lensHandlesImpl = address(new LensHandles(lensHandlesOwner, lensHub, HANDLE_GUARDIAN_COOLDOWN)); vm.stopBroadcast(); vm.writeLine(addressesFile, string.concat('FollowNFTImpl: ', vm.toString(followNFTImpl))); saveContractAddress('FollowNFTImpl', followNFTImpl); console.log('FollowNFTImpl: %s', followNFTImpl); vm.writeLine(addressesFile, string.concat('LensHandlesImpl: ', vm.toString(lensHandlesImpl))); saveContractAddress('LensHandlesImpl', lensHandlesImpl); console.log('LensHandlesImpl: %s', lensHandlesImpl); if (legacyCollectNFTImpl == address(0)) { console.log('LegacyCollectNFTImpl not set'); revert('LegacyCollectNFTImpl not set'); } if (moduleRegistry == address(0)) { console.log('ModuleRegistry not set'); revert('ModuleRegistry not set'); } if (PROFILE_GUARDIAN_COOLDOWN == 0) { console.log('PROFILE_GUARDIAN_COOLDOWN not set'); revert('PROFILE_GUARDIAN_COOLDOWN not set'); } console.log('PROFILE_GUARDIAN_COOLDOWN: %s', PROFILE_GUARDIAN_COOLDOWN); // Pass all the fucking shit and deploy LensHub V2 Impl with: vm.startBroadcast(_deployer.ownerPk); lensHubV2Impl = address( new LensHubInitializable( followNFTImpl, legacyCollectNFTImpl, moduleRegistry, PROFILE_GUARDIAN_COOLDOWN, Types.MigrationParams({ lensHandlesAddress: lensHandlesAddress, tokenHandleRegistryAddress: tokenHandleRegistryAddress, legacyFeeFollowModule: legacyFeeFollowModule, legacyProfileFollowModule: legacyProfileFollowModule, newFeeFollowModule: newFeeFollowModule }) ) ); vm.stopBroadcast(); console.log('"arguments": ['); console.log('\t"%s"', followNFTImpl); console.log('\t"%s"', legacyCollectNFTImpl); console.log('\t"%s"', moduleRegistry); console.log('\t"%s"', PROFILE_GUARDIAN_COOLDOWN); console.log( '\t"%s"', string.concat( '(', vm.toString(lensHandlesAddress), ', ', vm.toString(tokenHandleRegistryAddress), ', ', vm.toString(legacyFeeFollowModule), ', ', vm.toString(legacyProfileFollowModule), ', ', vm.toString(newFeeFollowModule), ')' ) ); console.log(']'); vm.writeLine(addressesFile, string.concat('LensHubV2Impl: ', vm.toString(lensHubV2Impl))); saveContractAddress('LensHubV2Impl', lensHubV2Impl); console.log('LensHubV2Impl: %s', lensHubV2Impl); } function run(string memory targetEnv_) external { targetEnv = targetEnv_; loadJson(); checkNetworkParams(); loadBaseAddresses(); loadPrivateKeys(); deploy(); } }