diff --git a/deployment-11155111.json b/deployment-11155111.json new file mode 100644 index 00000000..137e7921 --- /dev/null +++ b/deployment-11155111.json @@ -0,0 +1,18 @@ +{ + "main": { + "AccessControlSingleton-Impl": "0x9d78608605409d997f452b7E47410F6317b5312A", + "AccessControlSingleton-Proxy": "0xF3A6064ba0DBd98AdBb794136f534A53A2aC1aE5", + "IPAssetRegistry": "0x177175a4b26f6EA050676F8c9a14D395F896492C", + "IPOrgController-Impl": "0x01CCa0268c92b55FBC5360c76b3d39125DD39c9E", + "IPOrgController-Proxy": "0x73fCB515cEE99e4991465ef586CfE2B072EbB512", + "LicenseRegistry": "0x14b3b2b1700C9A1d5A5217dB92F0Ab54C7900563", + "LicensingModule": "0xa906E2589A7F8385A376BABBb70a39dad551603b", + "MockERC721": "0xe37983Ad02c0BEB88b334727d5A5a0dA6801F964", + "ModuleRegistry": "0x8DFd8d6673c5EDf13ACD0992a0Cd21dFB198F969", + "RegistrationModule": "0x091e5F55135155bb8Cb5868aDb39e5C34eB32CFd", + "RelationshipModule": "0x49477130a70a37E0D6e22b674ef9E923E6D0202c", + "StoryProtocol": "0x79448112dB0F3EaC69124e4bAd728ab74e1575Ea", + "TermsRepository": "0xCD5d06cFf106131A0845E2a18f8429D8115b3fD8", + "TokenGatedHook": "0xC0F6E387aC0B324Ec18EAcf22EE7271207dCE3d5" + } +} \ No newline at end of file diff --git a/deployment-31337.json b/deployment-31337.json index f1c8cdb8..e7fecba0 100644 --- a/deployment-31337.json +++ b/deployment-31337.json @@ -1,12 +1,19 @@ { "main": { - "AccessControlSingleton-Impl": "0x6E447CeC286dbaBe885fDbD9723DD63Cc2DE0Bd2", - "AccessControlSingleton-Proxy": "0xC06CBc0B7A136bda48865BE24228396Dea4094Ec", - "FranchiseRegistry-Impl": "0x446ce25bff9fe7049Aaf3339124F51F301e9c220", - "FranchiseRegistry-Proxy": "0x687E4e5a4471c259a8f56F1f06b0E5c5FEa808c8", - "IPAssetRegistryFactory": "0x7B4f9313d7a12aa902462860eeBD97ab2B68176F", - "ProtocolRelationshipModule-Impl": "0xa1833d78f09e2198774E612ca3d9879597ACc859", - "ProtocolRelationshipModule-Proxy": "0xd8562c2C2f7497D96C7Cf2f9E15392fe4c31c84f" + "AccessControlSingleton-Impl": "0x7B4f9313d7a12aa902462860eeBD97ab2B68176F", + "AccessControlSingleton-Proxy": "0x6E447CeC286dbaBe885fDbD9723DD63Cc2DE0Bd2", + "IPAssetRegistry": "0x446ce25bff9fe7049Aaf3339124F51F301e9c220", + "IPOrgController-Impl": "0xa1833d78f09e2198774E612ca3d9879597ACc859", + "IPOrgController-Proxy": "0xd8562c2C2f7497D96C7Cf2f9E15392fe4c31c84f", + "LicenseRegistry": "0x687E4e5a4471c259a8f56F1f06b0E5c5FEa808c8", + "LicensingModule": "0xb9162E7d63aDAC660f987755D45f55710EB5542a", + "MockERC721": "0x29715b74703b258D045fed347A8B3909aBdE5179", + "ModuleRegistry": "0xC06CBc0B7A136bda48865BE24228396Dea4094Ec", + "RegistrationModule": "0x869b721BbF176D0130d87E3aD2eEA02CEBB883eE", + "RelationshipModule": "0x812d70D430362c56E56F7Cfc73464FE2F1670ec9", + "StoryProtocol": "0xB61c296B51f542EeD7B76022c736488A571ac05b", + "TermsRepository": "0x0e0C15Fe242628fce34A123A0317C97f1D3256c8", + "TokenGatedHook": "0xdCc500f52a509F65023696FE7B717c81F8a432d5" }, "relationship-processors": { "DstOwnerRelationshipProcessor": "0x6E447CeC286dbaBe885fDbD9723DD63Cc2DE0Bd2", diff --git a/script/foundry/deployment/Main.s.sol b/script/foundry/deployment/Main.s.sol index 6ecaf1ec..11149c71 100644 --- a/script/foundry/deployment/Main.s.sol +++ b/script/foundry/deployment/Main.s.sol @@ -17,196 +17,288 @@ import "contracts/modules/royalties/RoyaltyNFT.sol"; import "contracts/ip-accounts/IPAccountImpl.sol"; import "contracts/ip-accounts/IPAccountRegistry.sol"; import { AccessControl } from "contracts/lib/AccessControl.sol"; +import "contracts/modules/ModuleRegistry.sol"; +import "contracts/IPAssetRegistry.sol"; +import "contracts/modules/registration/RegistrationModule.sol"; +import "contracts/StoryProtocol.sol"; +import "contracts/modules/base/BaseModule.sol"; +import "contracts/modules/licensing/LicenseRegistry.sol"; +import "contracts/modules/relationships/RelationshipModule.sol"; +import "contracts/lib/modules/ModuleRegistryKeys.sol"; +import "contracts/modules/licensing/LicensingModule.sol"; +import "contracts/hooks/TokenGatedHook.sol"; +import "contracts/modules/base/HookRegistry.sol"; +import "contracts/interfaces/hooks/base/IHook.sol"; +import { TokenGated } from "contracts/lib/hooks/TokenGated.sol"; +import "test/foundry/mocks/MockERC721.sol"; +import "contracts/modules/licensing/TermsRepository.sol"; +import { Licensing } from "contracts/lib/modules/Licensing.sol"; +import { TermCategories, TermIds } from "contracts/lib/modules/ProtocolLicensingTerms.sol"; + + contract Main is Script, BroadcastManager, JsonDeploymentHandler, ProxyHelper { + + using StringUtil for uint256; + using stdJson for string; + + address accessControl; + address ipOrgController; + address moduleRegistry; + address ipAssetRegistry; + address spg; + address licenseRegistry; + address registrationModule; + address relationshipModule; + address licensingModule; + address tokenGatedHook; + address mockNFT; + address termsRepository; + + + constructor() JsonDeploymentHandler("main") { + } + + /// @dev To use, run the following command (e.g. for Sepolia): + /// forge script script/Main.s.sol:Main --rpc-url $SEPOLIA_RPC_URL --broadcast --verify -vvvv + + function run() public { + _beginBroadcast(); + string memory contractKey; + address newAddress; + + /// ACCESS CONTROL SINGLETON + contractKey = "AccessControlSingleton-Impl"; -// contract Main is Script, BroadcastManager, JsonDeploymentHandler, ProxyHelper { + console.log(string.concat("Deploying ", contractKey, "...")); + newAddress = address(new AccessControlSingleton()); + _writeAddress(contractKey, newAddress); + console.log(string.concat(contractKey, " deployed to:"), newAddress); + -// using StringUtil for uint256; -// using stdJson for string; + contractKey = "AccessControlSingleton-Proxy"; -// address accessControl; -// address franchise; + console.log(string.concat("Deploying ", contractKey, "...")); + newAddress = _deployUUPSProxy( + newAddress, + abi.encodeWithSelector( + bytes4(keccak256(bytes("initialize(address)"))), admin + ) + ); + _writeAddress(contractKey, newAddress); + console.log(string.concat(contractKey, " deployed to:"), newAddress); -// string constant NON_COMMERCIAL_LICENSE_URI = "https://noncommercial.license"; -// string constant COMMERCIAL_LICENSE_URI = "https://commercial.license"; + accessControl = newAddress; -// constructor() JsonDeploymentHandler("main") { -// } + /// MODULE_REGISTRY + contractKey = "ModuleRegistry"; -// /// @dev To use, run the following command (e.g. for Goerli): -// /// forge script script/Deploy.s.sol:Deploy --rpc-url $GOERLI_RPC_URL --broadcast --verify -vvvv - -// function run() public { -// _beginBroadcast(); -// string memory contractKey; -// address newAddress; - -// /// ACCESS CONTROL SINGLETON -// contractKey = "AccessControlSingleton-Impl"; + console.log(string.concat("Deploying ", contractKey, "...")); + newAddress = address(new ModuleRegistry(accessControl)); + _writeAddress(contractKey, newAddress); + console.log(string.concat(contractKey, " deployed to:"), newAddress); -// console.log(string.concat("Deploying ", contractKey, "...")); -// newAddress = address(new AccessControlSingleton()); -// _writeAddress(contractKey, newAddress); -// console.log(string.concat(contractKey, " deployed to:"), newAddress); - + moduleRegistry = newAddress; -// contractKey = "AccessControlSingleton-Proxy"; + /// IP_ASSET_REGISTRY + contractKey = "IPAssetRegistry"; -// console.log(string.concat("Deploying ", contractKey, "...")); -// newAddress = _deployUUPSProxy( -// newAddress, -// abi.encodeWithSelector( -// bytes4(keccak256(bytes("initialize(address)"))), admin -// ) -// ); -// _writeAddress(contractKey, newAddress); -// console.log(string.concat(contractKey, " deployed to:"), newAddress); - -// accessControl = newAddress; - -// /// IP_ORG_FACTORY REGISTRY -// contractKey = "IPOrgController-Impl"; + console.log(string.concat("Deploying ", contractKey, "...")); + newAddress = address(new IPAssetRegistry(moduleRegistry)); + _writeAddress(contractKey, newAddress); + console.log(string.concat(contractKey, " deployed to:"), newAddress); -// console.log(string.concat("Deploying ", contractKey, "...")); -// newAddress = address(new IPOrgController()); -// _writeAddress(contractKey, newAddress); -// console.log(string.concat(contractKey, " deployed to:"), newAddress); - -// contractKey = "IPOrgController-Proxy"; - -// console.log(string.concat("Deploying ", contractKey, "...")); -// newAddress = _deployUUPSProxy( -// newAddress, -// abi.encodeWithSelector( -// bytes4(keccak256(bytes("initialize(address)"))), accessControl -// ) -// ); -// _writeAddress(contractKey, newAddress); -// console.log(string.concat(contractKey, " deployed to:"), newAddress); - -// franchise = newAddress; - -// /// LICENSING MODULE -// contractKey = "LicensingModule-Impl"; - -// console.log(string.concat("Deploying ", contractKey, "...")); - -// newAddress = address(new LicensingModule(address(franchise))); -// _writeAddress(contractKey, newAddress); -// console.log(string.concat(contractKey, " deployed to:"), newAddress); - -// contractKey = "LicensingModule-Proxy"; - -// console.log(string.concat("Deploying ", contractKey, "...")); -// newAddress = _deployUUPSProxy( -// newAddress, -// abi.encodeWithSelector( -// bytes4(keccak256(bytes("initialize(address,string)"))), -// accessControl, NON_COMMERCIAL_LICENSE_URI -// ) -// ); -// _writeAddress(contractKey, newAddress); -// console.log(string.concat(contractKey, " deployed to:"), newAddress); -// address licensingModule = newAddress; - -// /// COLLECT MODULE -// contractKey = "CollectNFT"; -// console.log(string.concat("Deploying ", contractKey, "...")); - -// newAddress = address(new MockCollectNFT()); -// _writeAddress(contractKey, newAddress); -// console.log(string.concat(contractKey, " deployed to:"), newAddress); - -// address defaultCollectNFTImpl = newAddress; - -// contractKey = "CollectModule-Impl"; -// console.log(string.concat("Deploying ", contractKey, "...")); - -// newAddress = address(new MockCollectModule(address(franchise), defaultCollectNFTImpl)); -// _writeAddress(contractKey, newAddress); -// console.log(string.concat(contractKey, " deployed to:"), newAddress); - -// contractKey = "CollectModule-Proxy"; - -// console.log(string.concat("Deploying ", contractKey, "...")); -// newAddress = _deployUUPSProxy( -// newAddress, -// abi.encodeWithSelector( -// bytes4(keccak256(bytes("initialize(address)"))), address(accessControl) -// ) -// ); -// _writeAddress(contractKey, newAddress); -// console.log(string.concat(contractKey, " deployed to:"), newAddress); -// address collectModule = newAddress; - - -// /// IP ACCOUNT REGISTRY -// contractKey = "IPAccount-Impl"; -// console.log(string.concat("Deploying ", contractKey, "...")); - -// newAddress = address(new IPAccountImpl()); -// _writeAddress(contractKey, newAddress); -// console.log(string.concat(contractKey, " deployed to:"), newAddress); - -// contractKey = "IPAccountRegistry"; -// console.log(string.concat("Deploying ", contractKey, "...")); - -// newAddress = address(new IPAccountRegistry(newAddress)); -// _writeAddress(contractKey, newAddress); -// console.log(string.concat(contractKey, " deployed to:"), newAddress); - -// address ipAccountRegistry = newAddress; - -// /// ROYALTY MODULE -// address SPLIT_MAIN = 0x2ed6c4B5dA6378c7897AC67Ba9e43102Feb694EE; -// contractKey = "RoyaltyNFT"; -// console.log(string.concat("Deploying ", contractKey, "...")); -// newAddress = address(new RoyaltyNFT(SPLIT_MAIN)); -// _writeAddress(contractKey, newAddress); -// console.log(string.concat(contractKey, " deployed to:"), newAddress); - -// address royaltyNft = newAddress; - -// contractKey = "MutableRoyaltyProportionPolicy"; -// console.log(string.concat("Deploying ", contractKey, "...")); -// newAddress = address(new MutableRoyaltyProportionPolicy(royaltyNft)); -// _writeAddress(contractKey, newAddress); -// console.log(string.concat(contractKey, " deployed to:"), newAddress); - -// contractKey = "RoyaltyDistributor"; -// console.log(string.concat("Deploying ", contractKey, "...")); -// newAddress = address(new RoyaltyDistributor(ipAccountRegistry, royaltyNft)); -// _writeAddress(contractKey, newAddress); -// console.log(string.concat(contractKey, " deployed to:"), newAddress); - -// /// PROTOCOL RELATIONSHIP MODULE -// contractKey = "ProtocolRelationshipModule-Impl"; - -// console.log(string.concat("Deploying ", contractKey, "...")); -// newAddress = address(new ProtocolRelationshipModule(franchise)); -// _writeAddress(contractKey, newAddress); -// console.log(string.concat(contractKey, " deployed to:"), newAddress); - + ipAssetRegistry = newAddress; -// contractKey = "ProtocolRelationshipModule-Proxy"; + /// LICENSE_REGISTRY + contractKey = "LicenseRegistry"; -// console.log(string.concat("Deploying ", contractKey, "...")); -// newAddress = _deployUUPSProxy( -// newAddress, -// abi.encodeWithSelector( -// bytes4(keccak256(bytes("initialize(address)"))), accessControl -// ) -// ); -// _writeAddress(contractKey, newAddress); -// console.log(string.concat(contractKey, " deployed to:"), newAddress); + console.log(string.concat("Deploying ", contractKey, "...")); + newAddress = address(new LicenseRegistry(ipAssetRegistry, moduleRegistry)); + _writeAddress(contractKey, newAddress); + console.log(string.concat(contractKey, " deployed to:"), newAddress); + licenseRegistry = newAddress; -// /// GRANT ROLEs -// AccessControlSingleton accessControlSingleton = AccessControlSingleton(accessControl); -// accessControlSingleton.grantRole(AccessControl.UPGRADER_ROLE, admin); -// accessControlSingleton.grantRole(AccessControl.RELATIONSHIP_MANAGER_ROLE, admin); - -// _writeDeployment(); -// _endBroadcast(); -// } - -// } + /// IP_ORG_FACTORY REGISTRY + contractKey = "IPOrgController-Impl"; + + console.log(string.concat("Deploying ", contractKey, "...")); + newAddress = address(new IPOrgController(moduleRegistry)); + _writeAddress(contractKey, newAddress); + console.log(string.concat(contractKey, " deployed to:"), newAddress); + + contractKey = "IPOrgController-Proxy"; + + console.log(string.concat("Deploying ", contractKey, "...")); + newAddress = _deployUUPSProxy( + newAddress, + abi.encodeWithSelector( + bytes4(keccak256(bytes("initialize(address)"))), accessControl + ) + ); + _writeAddress(contractKey, newAddress); + console.log(string.concat(contractKey, " deployed to:"), newAddress); + + ipOrgController = newAddress; + + /// SPG + contractKey = "StoryProtocol"; + + console.log(string.concat("Deploying ", contractKey, "...")); + newAddress = address(new StoryProtocol(IIPOrgController(ipOrgController), ModuleRegistry(moduleRegistry))); + _writeAddress(contractKey, newAddress); + console.log(string.concat(contractKey, " deployed to:"), newAddress); + + spg = newAddress; + + + /// REGISTRATION_MODULE + contractKey = "RegistrationModule"; + + console.log(string.concat("Deploying ", contractKey, "...")); + newAddress = address(new RegistrationModule(BaseModule.ModuleConstruction({ + ipaRegistry: IPAssetRegistry(ipAssetRegistry), + moduleRegistry: ModuleRegistry(moduleRegistry), + licenseRegistry: LicenseRegistry(licenseRegistry), + ipOrgController: IPOrgController(ipOrgController) + }), accessControl)); + _writeAddress(contractKey, newAddress); + console.log(string.concat(contractKey, " deployed to:"), newAddress); + + registrationModule = newAddress; + + + /// RELATIONSHIP_MODULE + contractKey = "RelationshipModule"; + + console.log(string.concat("Deploying ", contractKey, "...")); + newAddress = address(new RelationshipModule(BaseModule.ModuleConstruction({ + ipaRegistry: IPAssetRegistry(ipAssetRegistry), + moduleRegistry: ModuleRegistry(moduleRegistry), + licenseRegistry: LicenseRegistry(licenseRegistry), + ipOrgController: IPOrgController(ipOrgController) + }), accessControl)); + _writeAddress(contractKey, newAddress); + console.log(string.concat(contractKey, " deployed to:"), newAddress); + + relationshipModule = newAddress; + + /// TERMS_REPOSITORY + contractKey = "TermsRepository"; + + console.log(string.concat("Deploying ", contractKey, "...")); + newAddress = address(new TermsRepository(accessControl)); + _writeAddress(contractKey, newAddress); + console.log(string.concat(contractKey, " deployed to:"), newAddress); + + termsRepository = newAddress; + + /// LICENSE_MODULE + contractKey = "LicensingModule"; + + console.log(string.concat("Deploying ", contractKey, "...")); + newAddress = address(new LicensingModule(BaseModule.ModuleConstruction({ + ipaRegistry: IPAssetRegistry(ipAssetRegistry), + moduleRegistry: ModuleRegistry(moduleRegistry), + licenseRegistry: LicenseRegistry(licenseRegistry), + ipOrgController: IPOrgController(ipOrgController) + }), termsRepository) ); + _writeAddress(contractKey, newAddress); + console.log(string.concat(contractKey, " deployed to:"), newAddress); + + licensingModule = newAddress; + + + /// TOKEN_GATED_HOOK + contractKey = "TokenGatedHook"; + + console.log(string.concat("Deploying ", contractKey, "...")); + newAddress = address(new TokenGatedHook(accessControl)); + _writeAddress(contractKey, newAddress); + console.log(string.concat(contractKey, " deployed to:"), newAddress); + + tokenGatedHook = newAddress; + + /// MOCK_ERC_721 + contractKey = "MockERC721"; + + console.log(string.concat("Deploying ", contractKey, "...")); + newAddress = address(new MockERC721()); + _writeAddress(contractKey, newAddress); + console.log(string.concat(contractKey, " deployed to:"), newAddress); + + mockNFT = newAddress; + + + ///////////////////////////////////////////////////////////////////////////////////////////////////// + // CONFIGURATION // + ///////////////////////////////////////////////////////////////////////////////////////////////////// + + /// GRANT ROLEs + AccessControlSingleton accessControlSingleton = AccessControlSingleton(accessControl); + accessControlSingleton.grantRole(AccessControl.UPGRADER_ROLE, admin); + accessControlSingleton.grantRole(AccessControl.RELATIONSHIP_MANAGER_ROLE, admin); + accessControlSingleton.grantRole(AccessControl.LICENSING_MANAGER_ROLE, admin); + accessControlSingleton.grantRole(AccessControl.TERMS_SETTER_ROLE, admin); + accessControlSingleton.grantRole(AccessControl.IPORG_CREATOR_ROLE, admin); + accessControlSingleton.grantRole(AccessControl.MODULE_REGISTRAR_ROLE, admin); + accessControlSingleton.grantRole(AccessControl.MODULE_EXECUTOR_ROLE, spg); + + // REGISTER MODULES + ModuleRegistry(moduleRegistry).registerProtocolModule( + ModuleRegistryKeys.REGISTRATION_MODULE, BaseModule(registrationModule)); + ModuleRegistry(moduleRegistry).registerProtocolModule( + ModuleRegistryKeys.RELATIONSHIP_MODULE, BaseModule(relationshipModule)); + ModuleRegistry(moduleRegistry).registerProtocolModule( + ModuleRegistryKeys.LICENSING_MODULE, BaseModule(licensingModule)); + string[] memory ipAssetTypes = new string[](2); + ipAssetTypes[0] = "STORY"; + ipAssetTypes[1] = "CHARACTER"; + address ipOrg = StoryProtocol(spg).registerIpOrg(admin, "Sample IP Org", "SIPO", ipAssetTypes); + + // REGISTER TOKEN_GATED_HOOK + address[] memory hooks = new address[](1); + hooks[0] = tokenGatedHook; + + TokenGated.Config memory tokenGatedConfig = TokenGated.Config({ + tokenAddress: mockNFT + }); + bytes[] memory hooksConfig = new bytes[](1); + hooksConfig[0] = abi.encode(tokenGatedConfig); + RegistrationModule(registrationModule).registerHooks(HookRegistry.HookType.PreAction, IIPOrg(ipOrg), hooks, hooksConfig); + + // CONFIG LICENSING MODULE + Licensing.CommercialStatus comStatus = Licensing.CommercialStatus.Both; + TermsRepository(termsRepository).addCategory(TermCategories.SHARE_ALIKE); + Licensing.LicensingTerm memory term = _getTerm(TermIds.NFT_SHARE_ALIKE, comStatus); + TermsRepository(termsRepository).addTerm(TermCategories.SHARE_ALIKE, TermIds.NFT_SHARE_ALIKE, term); + + TermsRepository(termsRepository).addCategory(TermCategories.LICENSOR); + term = _getTerm(TermIds.LICENSOR_APPROVAL, comStatus); + TermsRepository(termsRepository).addTerm(TermCategories.LICENSOR, TermIds.LICENSOR_APPROVAL, term); + + TermsRepository(termsRepository).addCategory(TermCategories.CATEGORIZATION); + term = _getTerm(TermIds.FORMAT_CATEGORY, comStatus); + TermsRepository(termsRepository).addTerm(TermCategories.CATEGORIZATION, TermIds.FORMAT_CATEGORY, term); + + TermsRepository(termsRepository).addCategory(TermCategories.ACTIVATION); + term = _getTerm(TermIds.LICENSOR_IPORG_OR_PARENT, comStatus); + TermsRepository(termsRepository).addTerm(TermCategories.ACTIVATION, TermIds.LICENSOR_IPORG_OR_PARENT, term); + + + _writeDeployment(); + _endBroadcast(); + } + + function _getTerm( + string memory termId, + Licensing.CommercialStatus comStatus_ + ) internal pure returns (Licensing.LicensingTerm memory) { + return Licensing.LicensingTerm({ + comStatus: comStatus_, + url: string(abi.encodePacked("https://", termId,".com")), + hash: "qwertyu", + algorithm: "sha256", + hook: IHook(address(0)) + }); + } + } diff --git a/script/foundry/utils/BroadcastManager.s.sol b/script/foundry/utils/BroadcastManager.s.sol index 3abff0c5..e54f18ac 100644 --- a/script/foundry/utils/BroadcastManager.s.sol +++ b/script/foundry/utils/BroadcastManager.s.sol @@ -19,6 +19,10 @@ contract BroadcastManager is Script { deployerPrivateKey = vm.envUint("GOERLI_PRIVATEKEY"); admin = vm.envAddress("GOERLI_ADMIN_ADDRESS"); vm.startBroadcast(deployerPrivateKey); + } else if (block.chainid == 11155111) { + deployerPrivateKey = vm.envUint("SEPOLIA_PRIVATEKEY"); + admin = vm.envAddress("SEPOLIA_ADMIN_ADDRESS"); + vm.startBroadcast(deployerPrivateKey); } else { vm.startPrank(admin); }