misc: Script added to deploy fresh Lens V2

This commit is contained in:
donosonaumczuk
2024-04-04 17:01:22 -03:00
parent 81d592b5b6
commit ae716fc2fe

View File

@@ -0,0 +1,493 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {ForkManagement} from 'script/helpers/ForkManagement.sol';
import 'forge-std/Script.sol';
import {LensV2UpgradeContract} from 'contracts/misc/LensV2UpgradeContract.sol';
import {FollowNFT} from 'contracts/FollowNFT.sol';
import {LensHandles} from 'contracts/namespaces/LensHandles.sol';
import {TokenHandleRegistry} from 'contracts/namespaces/TokenHandleRegistry.sol';
import {TransparentUpgradeableProxy} from '@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.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 {LensHubInitializable} from 'contracts/misc/LensHubInitializable.sol';
import {ILensHub} from 'contracts/interfaces/ILensHub.sol';
import {ILensHandles} from 'contracts/interfaces/ILensHandles.sol';
import {ITokenHandleRegistry} from 'contracts/interfaces/ITokenHandleRegistry.sol';
import {PermissionlessCreator} from 'contracts/misc/PermissionlessCreator.sol';
import {CreditsFaucet} from 'contracts/misc/CreditsFaucet.sol';
import {CollectNFT} from 'contracts/modules/act/collect/CollectNFT.sol';
import {CollectPublicationAction} from 'contracts/modules/act/collect/CollectPublicationAction.sol';
import {SimpleFeeCollectModule} from 'contracts/modules/act/collect/SimpleFeeCollectModule.sol';
import {MultirecipientFeeCollectModule} from 'contracts/modules/act/collect/MultirecipientFeeCollectModule.sol';
import {FeeFollowModule} from './../contracts/modules/follow/FeeFollowModule.sol';
import {RevertFollowModule} from 'contracts/modules/follow/RevertFollowModule.sol';
import {DegreesOfSeparationReferenceModule} from 'contracts/modules/reference/DegreesOfSeparationReferenceModule.sol';
import {FollowerOnlyReferenceModule} from 'contracts/modules/reference/FollowerOnlyReferenceModule.sol';
import {TokenGatedReferenceModule} from 'contracts/modules/reference/TokenGatedReferenceModule.sol';
import {Types} from 'contracts/libraries/constants/Types.sol';
import {ModuleRegistry} from 'contracts/misc/ModuleRegistry.sol';
import {IModuleRegistry} from 'contracts/interfaces/IModuleRegistry.sol';
import {LitAccessControl} from 'contracts/misc/access/LitAccessControl.sol';
import {PublicActProxy} from './../contracts/misc/PublicActProxy.sol';
import {Governance} from './../contracts/misc/access/Governance.sol';
import {ProxyAdmin} from './../contracts/misc/access/ProxyAdmin.sol';
import {ERC2981CollectionRoyalties} from './../contracts/base/ERC2981CollectionRoyalties.sol';
import {ArrayHelpers} from 'test/helpers/ArrayHelpers.sol';
contract DeployFreshLensV2 is Script, ForkManagement, ArrayHelpers {
using stdJson for string;
string addressesFile = 'addressesV2.txt';
bytes32 constant ADMIN_SLOT = bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1);
string mnemonic;
uint256 internal PROFILE_GUARDIAN_COOLDOWN;
uint256 internal HANDLE_GUARDIAN_COOLDOWN;
struct LensAccount {
uint256 ownerPk;
address owner;
uint256 profileId;
}
LensAccount deployer;
LensAccount governance;
LensAccount proxyAdmin;
LensAccount treasury;
LensAccount profileCreator;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ModuleRegistry moduleRegistryImpl;
TransparentUpgradeableProxy moduleRegistryProxy;
ModuleRegistry moduleRegistry;
FollowNFT followNFT;
LensHubInitializable lensHubImpl;
TransparentUpgradeableProxy hubProxy;
ILensHub hub;
LensHandles handlesImpl;
TransparentUpgradeableProxy handlesProxy;
ILensHandles handles;
TokenHandleRegistry tokenHandleRegistryImpl;
TransparentUpgradeableProxy tokenHandleRegistryProxy;
ITokenHandleRegistry tokenHandleRegistry;
PermissionlessCreator permissionlessCreatorImpl;
TransparentUpgradeableProxy permissionlessCreatorProxy;
PermissionlessCreator permissionlessCreator;
CreditsFaucet creditsFaucet;
CollectNFT collectNFT;
CollectPublicationAction collectPublicationActionImpl;
TransparentUpgradeableProxy collectPublicationActionProxy;
CollectPublicationAction collectPublicationAction;
SimpleFeeCollectModule simpleFeeCollectModule;
MultirecipientFeeCollectModule multirecipientFeeCollectModule;
FeeFollowModule feeFollowModule;
RevertFollowModule revertFollowModule;
DegreesOfSeparationReferenceModule degreesOfSeparationReferenceModule;
FollowerOnlyReferenceModule followerOnlyReferenceModule;
TokenGatedReferenceModule tokenGatedReferenceModule;
LitAccessControl litAccessControlImpl;
TransparentUpgradeableProxy litAccessControlProxy;
LitAccessControl litAccessControl;
PublicActProxy publicActProxy;
Governance governanceContract;
ProxyAdmin proxyAdminContract;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function loadPrivateKeys() internal {
if (isEnvSet('MNEMONIC')) {
mnemonic = vm.envString('MNEMONIC');
}
if (bytes(mnemonic).length == 0) {
revert('Missing mnemonic');
}
console.log('\n- - - CURRENT BLOCK: ', block.number);
(deployer.owner, deployer.ownerPk) = deriveRememberKey(mnemonic, 0);
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 loadDeployParams() internal {
HANDLE_GUARDIAN_COOLDOWN = json.readUint(
string(abi.encodePacked('.', targetEnv, '.LensHandlesGuardianTimelock'))
);
if (HANDLE_GUARDIAN_COOLDOWN == 0) {
console.log('HANDLE_GUARDIAN_COOLDOWN not set');
revert('HANDLE_GUARDIAN_COOLDOWN not set');
}
console.log('HANDLE_GUARDIAN_COOLDOWN: %s', HANDLE_GUARDIAN_COOLDOWN);
PROFILE_GUARDIAN_COOLDOWN = json.readUint(
string(abi.encodePacked('.', targetEnv, '.LensProfilesGuardianTimelock'))
);
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);
}
function _deployCore() internal {
moduleRegistryImpl = new ModuleRegistry();
_logDeployedAddress(address(moduleRegistryImpl), 'ModuleRegistryImpl');
moduleRegistryProxy = new TransparentUpgradeableProxy({
_logic: address(moduleRegistryImpl),
admin_: proxyAdmin.owner,
_data: ''
});
_logDeployedAddress(address(moduleRegistryProxy), '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);
_logDeployedAddress(address(followNFT), '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: PROFILE_GUARDIAN_COOLDOWN,
migrationParams: Types.MigrationParams({
lensHandlesAddress: address(0),
tokenHandleRegistryAddress: address(0),
legacyFeeFollowModule: address(0),
legacyProfileFollowModule: address(0),
newFeeFollowModule: address(0)
}) // No needed on a fresh V2 deployment, no migration needed.
});
_logDeployedAddress(address(lensHubImpl), '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));
_logDeployedAddress(address(hub), 'LensHubProxy');
handlesImpl = new LensHandles({
owner: governance.owner,
lensHub: address(hub),
tokenGuardianCooldown: HANDLE_GUARDIAN_COOLDOWN
});
_logDeployedAddress(address(handlesImpl), 'LensHandlesImpl');
handlesProxy = new TransparentUpgradeableProxy({
_logic: address(handlesImpl),
admin_: proxyAdmin.owner,
_data: ''
});
_logDeployedAddress(address(handlesProxy), 'LensHandles');
handles = ILensHandles(address(handlesProxy));
tokenHandleRegistryImpl = new TokenHandleRegistry({lensHub: address(hub), lensHandles: address(handles)});
_logDeployedAddress(address(tokenHandleRegistryImpl), 'TokenHandleRegistryImpl');
tokenHandleRegistryProxy = new TransparentUpgradeableProxy({
_logic: address(tokenHandleRegistryImpl),
admin_: proxyAdmin.owner,
_data: ''
});
_logDeployedAddress(address(tokenHandleRegistryProxy), 'TokenHandleRegistry');
tokenHandleRegistry = ITokenHandleRegistry(address(tokenHandleRegistryProxy));
permissionlessCreatorImpl = new PermissionlessCreator(
governance.owner,
address(hub),
address(handles),
address(tokenHandleRegistry)
);
permissionlessCreatorProxy = new TransparentUpgradeableProxy({
_logic: address(permissionlessCreatorImpl),
admin_: proxyAdmin.owner,
_data: ''
});
permissionlessCreator = PermissionlessCreator(address(permissionlessCreatorProxy));
_logDeployedAddress(address(permissionlessCreator), 'PermissionlessCreator');
if (isTestnet) {
creditsFaucet = new CreditsFaucet(address(permissionlessCreatorProxy));
_logDeployedAddress(address(creditsFaucet), 'CreditsFaucet');
// Credit faucet is added as provider in the permissionless creator later in this script.
}
currentDeployerNonce = vm.getNonce(deployer.owner);
/**
* CollectNFT (currentDeployerNonce)
* CollectPublicationAction aka CollectPublicationActionImpl (currentDeployerNonce + 1)
* TransparentUpgradeableProxy aka CollectPublicationActionProxy (currentDeployerNonce + 2)
*/
uint256 collectPublicationActionProxyDeploymentNonce = currentDeployerNonce + 2;
address expectedCollectPublicationActionProxyAddress = computeCreateAddress(
deployer.owner,
collectPublicationActionProxyDeploymentNonce
);
collectNFT = new CollectNFT({hub: address(hub), actionModule: expectedCollectPublicationActionProxyAddress});
_logDeployedAddress(address(collectNFT), 'CollectNFT');
collectPublicationActionImpl = new CollectPublicationAction({
hub: address(hub),
collectNFTImpl: address(collectNFT),
moduleOwner: governance.owner
});
_logDeployedAddress(address(collectPublicationActionImpl), 'CollectPublicationActionImpl');
collectPublicationActionProxy = new TransparentUpgradeableProxy({
_logic: address(collectPublicationActionImpl),
admin_: proxyAdmin.owner,
_data: ''
});
_logDeployedAddress(address(collectPublicationActionProxy), 'CollectPublicationActionProxy');
collectPublicationAction = CollectPublicationAction(address(collectPublicationActionProxy));
}
function _deployFollowModules() internal {
feeFollowModule = new FeeFollowModule({
hub: address(hub),
moduleRegistry: address(moduleRegistry),
moduleOwner: governance.owner
});
_logDeployedAddress(address(feeFollowModule), 'FeeFollowModule');
revertFollowModule = new RevertFollowModule({moduleOwner: governance.owner});
_logDeployedAddress(address(revertFollowModule), 'RevertFollowModule');
}
function _deployCollectModules() internal {
simpleFeeCollectModule = new SimpleFeeCollectModule({
hub: address(hub),
actionModule: address(collectPublicationActionProxy),
moduleRegistry: address(moduleRegistry),
moduleOwner: governance.owner
});
_logDeployedAddress(address(simpleFeeCollectModule), 'SimpleFeeCollectModule');
multirecipientFeeCollectModule = new MultirecipientFeeCollectModule({
hub: address(hub),
actionModule: address(collectPublicationActionProxy),
moduleRegistry: address(moduleRegistry),
moduleOwner: governance.owner
});
_logDeployedAddress(address(multirecipientFeeCollectModule), 'MultirecipientFeeCollectModule');
}
function _deployReferenceModules() internal {
degreesOfSeparationReferenceModule = new DegreesOfSeparationReferenceModule({
hub: address(hub),
moduleOwner: governance.owner
});
_logDeployedAddress(address(degreesOfSeparationReferenceModule), 'DegreesOfSeparationReferenceModule');
followerOnlyReferenceModule = new FollowerOnlyReferenceModule({
hub: address(hub),
moduleOwner: governance.owner
});
_logDeployedAddress(address(followerOnlyReferenceModule), 'FollowerOnlyReferenceModule');
}
function _deployPeripherialContracts() internal {
litAccessControlImpl = new LitAccessControl(address(hub), address(collectPublicationAction));
litAccessControlProxy = new TransparentUpgradeableProxy({
_logic: address(litAccessControlImpl),
admin_: proxyAdmin.owner,
_data: ''
});
litAccessControl = LitAccessControl(address(litAccessControlProxy));
_logDeployedAddress(address(litAccessControl), 'LitAccessControl');
publicActProxy = new PublicActProxy({
lensHub: address(hub),
collectPublicationAction: address(collectPublicationAction)
});
_logDeployedAddress(address(publicActProxy), 'PublicActProxy');
}
// TODO: Use from test/ContractAddresses?
struct Currency {
address addy;
string symbol;
}
function _registerCurrencies() internal {
console.log('\n[Registering currencies]');
Currency[] memory currencies = abi.decode(
vm.parseJson(json, string(abi.encodePacked('.', targetEnv, '.Currencies'))),
(Currency[])
);
for (uint256 i = 0; i < currencies.length; i++) {
moduleRegistry.registerErc20Currency(currencies[i].addy);
console.log('\n* * * ', currencies[i].symbol, ' registered as currency: ', currencies[i].addy);
vm.writeLine(
addressesFile,
string.concat(currencies[i].symbol, string.concat(': ', vm.toString(currencies[i].addy)))
);
}
}
function _registerModules() internal {
// Follow modules
moduleRegistry.registerModule(address(feeFollowModule), uint256(IModuleRegistry.ModuleType.FOLLOW_MODULE));
console.log('\n* * * FeeFollowModule registered as follow module');
moduleRegistry.registerModule(address(revertFollowModule), uint256(IModuleRegistry.ModuleType.FOLLOW_MODULE));
console.log('\n* * * RevertFollowModule registered as follow module');
// Reference modules
moduleRegistry.registerModule(
address(degreesOfSeparationReferenceModule),
uint256(IModuleRegistry.ModuleType.REFERENCE_MODULE)
);
console.log('\n* * * DegreesOfSeparationReferenceModule registered');
moduleRegistry.registerModule(
address(followerOnlyReferenceModule),
uint256(IModuleRegistry.ModuleType.REFERENCE_MODULE)
);
console.log('\n* * * FollowerOnlyReferenceModule registered');
// Collect modules
moduleRegistry.registerModule(
address(collectPublicationAction),
uint256(IModuleRegistry.ModuleType.PUBLICATION_ACTION_MODULE)
);
console.log('\n* * * CollectPublicationAction registered as action module');
collectPublicationAction.registerCollectModule(address(simpleFeeCollectModule));
console.log('\n* * * SimpleFeeCollectModule registered as collect module');
collectPublicationAction.registerCollectModule(address(multirecipientFeeCollectModule));
console.log('\n* * * MultirecipientFeeCollectModule registered as collect module');
}
function _logDeployedAddress(address deployedAddress, string memory addressLabel) internal {
console.log('\n+ + + ', addressLabel, ': ', deployedAddress);
vm.writeLine(addressesFile, string.concat(addressLabel, string.concat(': ', vm.toString(deployedAddress))));
}
function deploy() internal {
loadDeployParams();
vm.startBroadcast(deployer.ownerPk);
{
_deployCore();
_deployCollectModules();
_deployFollowModules();
_deployReferenceModules();
_deployPeripherialContracts();
}
vm.stopBroadcast();
vm.startBroadcast(governance.ownerPk);
{
if (isTestnet) {
console.log('\n[Adding Credits Faucet as Credit Provider]');
permissionlessCreator.addCreditProvider(address(creditsFaucet));
}
_registerCurrencies();
hub.whitelistProfileCreator(address(permissionlessCreator), true);
console.log('\n* * * Permissionless creator contract registered as profile creator');
_registerModules();
hub.setState(Types.ProtocolState.Unpaused);
console.log('\n* * * Protocol unpaused');
hub.setTreasury(address(treasury.owner));
uint256 treasuryFee = json.readUint(string(abi.encodePacked('.', targetEnv, '.TreasuryFee')));
if (treasuryFee > 10_000) {
revert('Treasury fee exceeding max BPS');
}
hub.setTreasuryFee(uint16(treasuryFee));
uint256 profileRoyaltyFee = json.readUint(string(abi.encodePacked('.', targetEnv, '.ProfileRoyaltyFee')));
ERC2981CollectionRoyalties(address(hub)).setRoyalty(profileRoyaltyFee);
uint256 handleRoyaltyFee = json.readUint(string(abi.encodePacked('.', targetEnv, '.HandleRoyaltyFee')));
ERC2981CollectionRoyalties(address(handles)).setRoyalty(handleRoyaltyFee);
uint256 anonymousProfileId = permissionlessCreator.createProfile({
createProfileParams: Types.CreateProfileParams({
to: deployer.owner,
followModule: address(0),
followModuleInitData: ''
}),
delegatedExecutors: new address[](0)
});
vm.writeLine(addressesFile, string.concat('AnonymousProfileId :', vm.toString(anonymousProfileId)));
}
vm.stopBroadcast();
vm.startBroadcast(deployer.ownerPk);
{
// Deploy governance and proxy-admin controllable-by-contract contracts, and transfer ownership.
governanceContract = new Governance(address(hub), governance.owner);
_logDeployedAddress(address(governanceContract), 'GovernanceContract');
proxyAdminContract = new ProxyAdmin(address(hub), address(0), proxyAdmin.owner);
_logDeployedAddress(address(proxyAdminContract), 'ProxyAdminContract');
}
vm.stopBroadcast();
vm.startBroadcast(governance.ownerPk);
{
hub.setGovernance(address(governanceContract));
// hub.setEmergencyAdmin(governance.owner); // TODO: WHO ?
}
vm.stopBroadcast();
vm.startBroadcast(proxyAdmin.ownerPk);
{
hubProxy.changeAdmin(address(proxyAdminContract));
}
vm.stopBroadcast();
}
function run(string memory targetEnv_) external {
targetEnv = targetEnv_;
loadJson();
checkNetworkParams();
loadPrivateKeys();
deploy();
// _writeBackendEnvFile();
// _interact();
}
}