From ec35ce0b194dbf8f61a408dd546e2a8c76475777 Mon Sep 17 00:00:00 2001 From: Jongwon Park Date: Mon, 8 Apr 2024 21:31:18 -0500 Subject: [PATCH] Single DeployHelper for Deployment and Tests (#36) - Use new BaseTest and remove mock deployers - Modify some tests to clarify on caller using vm prank - Minor lint fixes for state variable visibility - Mock royalty policy LAP - Prepare codebase structure to remove some mocks in next PR - Remove unused test files - refactor(script): Remove deployment of IPAccountRegistry and use alt --- .github/workflows/foundry_ci.yml | 2 +- script/foundry/deployment/Main.s.sol | 617 +----------------- script/foundry/utils/BroadcastManager.s.sol | 11 +- script/foundry/utils/DeployHelper.sol | 373 +++++++++++ .../foundry/utils/JsonDeploymentHandler.s.sol | 11 +- test/foundry/IPAccount.t.sol | 6 +- test/foundry/IPAccountMetaTx.t.sol | 5 +- test/foundry/IPAccountStorage.t.sol | 2 - test/foundry/IPAccountStorageOps.t.sol | 2 - test/foundry/access/AccessControlled.t.sol | 5 +- test/foundry/access/AccessController.t.sol | 60 +- test/foundry/governance/Governance.t.sol | 4 - .../foundry/integration/BaseIntegration.t.sol | 10 - .../integration/flows/disputes/Disputes.t.sol | 2 +- .../EmergenceUniverse.t.sol | 16 - .../flows/emergence-universe/README.md | 10 - .../flows/licensing/LicensingScenarios.t.sol | 2 +- .../integration/flows/royalty/Royalty.t.sol | 6 +- .../mocks/policy/MockRoyaltyPolicyLAP.sol | 74 +++ test/foundry/modules/ModuleBase.t.sol | 3 - .../modules/dispute/ArbitrationPolicySP.t.sol | 6 - .../modules/dispute/DisputeModule.t.sol | 11 +- .../external/TokenWithdrawalModule.t.sol | 17 +- .../modules/licensing/LicensingModule.t.sol | 35 +- .../PILPolicyFramework.derivation.t.sol | 21 +- .../PILPolicyFramework.multi-parent.sol | 23 +- .../licensing/PILPolicyFramework.t.sol | 20 - .../modules/metadata/CoreMetadataModule.t.sol | 12 - .../metadata/CoreMetadataViewModule.t.sol | 19 - .../modules/metadata/MetadataModule.t.sol | 14 +- .../modules/royalty/IpRoyaltyVault.t.sol | 8 +- .../modules/royalty/RoyaltyModule.t.sol | 16 +- .../modules/royalty/RoyaltyPolicyLAP.t.sol | 6 - .../registries/IPAccountRegistry.t.sol | 2 - test/foundry/registries/IPAssetRegistry.t.sol | 8 - test/foundry/registries/ModuleRegistry.t.sol | 3 - test/foundry/utils/BaseTest.t.sol | 170 +---- test/foundry/utils/DeployHelper.t.sol | 396 ----------- 38 files changed, 578 insertions(+), 1430 deletions(-) create mode 100644 script/foundry/utils/DeployHelper.sol delete mode 100644 test/foundry/integration/flows/emergence-universe/EmergenceUniverse.t.sol delete mode 100644 test/foundry/integration/flows/emergence-universe/README.md create mode 100644 test/foundry/mocks/policy/MockRoyaltyPolicyLAP.sol delete mode 100644 test/foundry/utils/DeployHelper.t.sol diff --git a/.github/workflows/foundry_ci.yml b/.github/workflows/foundry_ci.yml index 74fdaccd..e62faa6b 100644 --- a/.github/workflows/foundry_ci.yml +++ b/.github/workflows/foundry_ci.yml @@ -55,7 +55,7 @@ jobs: - name: Run Forge tests run: | - forge test -vvv --fork-url https://gateway.tenderly.co/public/sepolia --fork-block-number 5196000 + forge test -vvv id: forge-test - name: Run solhint diff --git a/script/foundry/deployment/Main.s.sol b/script/foundry/deployment/Main.s.sol index ac8601e4..7505aefb 100644 --- a/script/foundry/deployment/Main.s.sol +++ b/script/foundry/deployment/Main.s.sol @@ -2,115 +2,31 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.23; -// external -import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import { console2 } from "forge-std/console2.sol"; -import { Script } from "forge-std/Script.sol"; -import { stdJson } from "forge-std/StdJson.sol"; -// TODO: fix the install of this plugin for safer deployments -// import { Upgrades } from "openzeppelin-foundry-upgrades/Upgrades.sol"; -import { TestProxyHelper } from "test/foundry/utils/TestProxyHelper.sol"; - -// contracts -import { AccessController } from "contracts/access/AccessController.sol"; -import { IPAccountImpl } from "contracts/IPAccountImpl.sol"; -import { IIPAccount } from "contracts/interfaces/IIPAccount.sol"; -import { IRoyaltyPolicyLAP } from "contracts/interfaces/modules/royalty/policies/IRoyaltyPolicyLAP.sol"; -import { Governance } from "contracts/governance/Governance.sol"; -import { AccessPermission } from "contracts/lib/AccessPermission.sol"; -import { Errors } from "contracts/lib/Errors.sol"; -import { PILFlavors } from "contracts/lib/PILFlavors.sol"; -// solhint-disable-next-line max-line-length -import { DISPUTE_MODULE_KEY, ROYALTY_MODULE_KEY, LICENSING_MODULE_KEY, TOKEN_WITHDRAWAL_MODULE_KEY, CORE_METADATA_MODULE_KEY, CORE_METADATA_VIEW_MODULE_KEY } from "contracts/lib/modules/Module.sol"; -import { IPAccountRegistry } from "contracts/registries/IPAccountRegistry.sol"; -import { IPAssetRegistry } from "contracts/registries/IPAssetRegistry.sol"; -import { ModuleRegistry } from "contracts/registries/ModuleRegistry.sol"; -import { LicenseRegistry } from "contracts/registries/LicenseRegistry.sol"; -import {LicenseToken} from "contracts/LicenseToken.sol"; -import { LicensingModule } from "contracts/modules/licensing/LicensingModule.sol"; -import { RoyaltyModule } from "contracts/modules/royalty/RoyaltyModule.sol"; -import { CoreMetadataModule } from "contracts/modules/metadata/CoreMetadataModule.sol"; -import { CoreMetadataViewModule } from "contracts/modules/metadata/CoreMetadataViewModule.sol"; -import { RoyaltyPolicyLAP } from "contracts/modules/royalty/policies/RoyaltyPolicyLAP.sol"; -import { DisputeModule } from "contracts/modules/dispute/DisputeModule.sol"; -import { ArbitrationPolicySP } from "contracts/modules/dispute/policies/ArbitrationPolicySP.sol"; -import { TokenWithdrawalModule } from "contracts/modules/external/TokenWithdrawalModule.sol"; -// solhint-disable-next-line max-line-length -import { PILicenseTemplate, PILTerms} from "contracts/modules/licensing/PILicenseTemplate.sol"; -import { MODULE_TYPE_HOOK } from "contracts/lib/modules/Module.sol"; -import { IModule } from "contracts/interfaces/modules/base/IModule.sol"; -import { IHookModule } from "contracts/interfaces/modules/base/IHookModule.sol"; // script -import { StringUtil } from "../../../script/foundry/utils/StringUtil.sol"; -import { BroadcastManager } from "../../../script/foundry/utils/BroadcastManager.s.sol"; -import { JsonDeploymentHandler } from "../../../script/foundry/utils/JsonDeploymentHandler.s.sol"; -import { StorageLayoutChecker } from "../../../script/foundry/utils/upgrades/StorageLayoutCheck.s.sol"; - -// test -import { MockERC20 } from "test/foundry/mocks/token/MockERC20.sol"; -import { MockERC721 } from "test/foundry/mocks/token/MockERC721.sol"; -import { MockTokenGatedHook } from "test/foundry/mocks/MockTokenGatedHook.sol"; - -contract Main is Script, BroadcastManager, JsonDeploymentHandler, StorageLayoutChecker { - using StringUtil for uint256; - using stdJson for string; +import { DeployHelper } from "../utils/DeployHelper.sol"; +contract Main is DeployHelper { address internal ERC6551_REGISTRY = 0x000000006551c19487814612e58FE06813775758; - IPAccountImpl internal ipAccountImpl; - - // Registry - IPAccountRegistry internal ipAccountRegistry; - IPAssetRegistry internal ipAssetRegistry; - LicenseRegistry internal licenseRegistry; - LicenseToken internal licenseToken; - ModuleRegistry internal moduleRegistry; - - // Core Module - CoreMetadataModule internal coreMetadataModule; - CoreMetadataViewModule internal coreMetadataViewModule; - LicensingModule internal licensingModule; - DisputeModule internal disputeModule; - RoyaltyModule internal royaltyModule; - - // External Module - TokenWithdrawalModule internal tokenWithdrawalModule; - - // Policy - ArbitrationPolicySP internal arbitrationPolicySP; - RoyaltyPolicyLAP internal royaltyPolicyLAP; - PILicenseTemplate internal piLt; - - // Misc. - Governance internal governance; - AccessController internal accessController; - - // Mocks - MockERC20 internal erc20; - MockERC721 internal erc721; - - // Hooks - MockTokenGatedHook internal mockTokenGatedHook; - - mapping(uint256 tokenId => address ipAccountAddress) internal ipAcct; - - mapping(string policyName => uint256 policyId) internal policyIds; - - mapping(string frameworkName => address frameworkAddr) internal templateAddrs; - - uint256 internal constant ARBITRATION_PRICE = 1000 * 10 ** 6; // 1000 MockToken + // For arbitration policy + uint256 internal constant ARBITRATION_PRICE = 1000 * 10 ** 6; // 1000 USDC + // For royalty policy uint256 internal constant MAX_ROYALTY_APPROVAL = 10000 ether; - constructor() JsonDeploymentHandler("main") {} + constructor() + DeployHelper( + ERC6551_REGISTRY, + address(0), // replaced with USDC in DeployHelper.sol + ARBITRATION_PRICE, + MAX_ROYALTY_APPROVAL + ) + {} /// @dev To use, run the following command (e.g. for Sepolia): /// forge script script/foundry/deployment/Main.s.sol:Main --rpc-url $RPC_URL --broadcast --verify -vvvv function run() public virtual override { - // This will run OZ storage layout check for all contracts. Requires --ffi flag. - super.run(); - _beginBroadcast(); // BroadcastManager.s.sol - bool configByMultisig; try vm.envBool("DEPLOYMENT_CONFIG_BY_MULTISIG") returns (bool mult) { configByMultisig = mult; @@ -119,507 +35,14 @@ contract Main is Script, BroadcastManager, JsonDeploymentHandler, StorageLayoutC } console2.log("configByMultisig:", configByMultisig); - if (configByMultisig) { - _deployProtocolContracts(multisig); - } else { - _deployProtocolContracts(deployer); - _configureDeployment(); - } - + // deploy all contracts via DeployHelper + super.run( + configByMultisig ? multisig : deployer, // deployer + configByMultisig, + false, // runStorageLayoutCheck + true // writeDeploys + ); _writeDeployment(); // write deployment json to deployments/deployment-{chainId}.json _endBroadcast(); // BroadcastManager.s.sol } - - function _deployProtocolContracts(address accessControlDeployer) private { - string memory contractKey; - - // Mock Assets (deploy first) - - contractKey = "MockERC20"; - _predeploy(contractKey); - erc20 = new MockERC20(); - _postdeploy(contractKey, address(erc20)); - - contractKey = "MockERC721"; - _predeploy(contractKey); - erc721 = new MockERC721("MockERC721"); - _postdeploy(contractKey, address(erc721)); - - // Core Protocol Contracts - - contractKey = "Governance"; - _predeploy(contractKey); - governance = new Governance(accessControlDeployer); - _postdeploy(contractKey, address(governance)); - - contractKey = "AccessController"; - _predeploy(contractKey); - - address impl = address(new AccessController()); - accessController = AccessController( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(AccessController.initialize, address(governance))) - ); - impl = address(0); // Make sure we don't deploy wrong impl - _postdeploy(contractKey, address(accessController)); - - contractKey = "IPAccountImpl"; - _predeploy(contractKey); - ipAccountImpl = new IPAccountImpl(address(accessController)); - _postdeploy(contractKey, address(ipAccountImpl)); - - contractKey = "ModuleRegistry"; - _predeploy(contractKey); - impl = address(new ModuleRegistry()); - moduleRegistry = ModuleRegistry( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(ModuleRegistry.initialize, address(governance))) - ); - impl = address(0); // Make sure we don't deploy wrong impl - _postdeploy(contractKey, address(moduleRegistry)); - - contractKey = "IPAccountRegistry"; - _predeploy(contractKey); - ipAccountRegistry = new IPAccountRegistry(ERC6551_REGISTRY, address(ipAccountImpl)); - _postdeploy(contractKey, address(ipAccountRegistry)); - - contractKey = "IPAssetRegistry"; - _predeploy(contractKey); - ipAssetRegistry = new IPAssetRegistry( - ERC6551_REGISTRY, - address(ipAccountImpl), - address(governance) - ); - _postdeploy(contractKey, address(ipAssetRegistry)); - - contractKey = "RoyaltyModule"; - _predeploy(contractKey); - impl = address(new RoyaltyModule()); - royaltyModule = RoyaltyModule( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(RoyaltyModule.initialize, (address(governance)))) - ); - impl = address(0); - _postdeploy(contractKey, address(royaltyModule)); - - contractKey = "DisputeModule"; - _predeploy(contractKey); - impl = address(new DisputeModule(address(accessController), address(ipAssetRegistry))); - disputeModule = DisputeModule( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(DisputeModule.initialize, (address(governance)))) - ); - impl = address(0); - _postdeploy(contractKey, address(disputeModule)); - - contractKey = "LicenseRegistry"; - _predeploy(contractKey); - impl = address(new LicenseRegistry()); - licenseRegistry = LicenseRegistry( - TestProxyHelper.deployUUPSProxy( - impl, - abi.encodeCall( - LicenseRegistry.initialize, - ( - address(governance) - ) - ) - ) - ); - impl = address(0); // Make sure we don't deploy wrong impl - _postdeploy(contractKey, address(licenseRegistry)); - - contractKey = "LicenseToken"; - _predeploy(contractKey); - impl = address(new LicenseToken()); - licenseToken = LicenseToken( - TestProxyHelper.deployUUPSProxy( - impl, - abi.encodeCall( - LicenseToken.initialize, - ( - address(governance), - "https://github.com/storyprotocol/protocol-core/blob/main/assets/license-image.gif" - ) - ) - ) - ); - impl = address(0); // Make sure we don't deploy wrong impl - _postdeploy(contractKey, address(licenseToken)); - - contractKey = "LicensingModule"; - _predeploy(contractKey); - - impl = address( - new LicensingModule( - address(accessController), - address(ipAccountRegistry), - address(royaltyModule), - address(licenseRegistry), - address(disputeModule), - address(licenseToken) - ) - ); - licensingModule = LicensingModule( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(LicensingModule.initialize, address(governance))) - ); - impl = address(0); // Make sure we don't deploy wrong impl - _postdeploy(contractKey, address(licensingModule)); - - contractKey = "TokenWithdrawalModule"; - _predeploy(contractKey); - tokenWithdrawalModule = new TokenWithdrawalModule(address(accessController), address(ipAccountRegistry)); - _postdeploy(contractKey, address(tokenWithdrawalModule)); - - contractKey = "CoreMetadataModule"; - _predeploy(contractKey); - coreMetadataModule = new CoreMetadataModule(address(accessController), address(ipAccountRegistry)); - _postdeploy(contractKey, address(coreMetadataModule)); - - contractKey = "CoreMetadataViewModule"; - _predeploy(contractKey); - coreMetadataViewModule = new CoreMetadataViewModule(address(ipAssetRegistry), address(moduleRegistry)); - _postdeploy(contractKey, address(coreMetadataModule)); - - - // - // Story-specific Contracts - // - - contractKey = "ArbitrationPolicySP"; - _predeploy(contractKey); - impl = address(new ArbitrationPolicySP(address(disputeModule), address(erc20), ARBITRATION_PRICE)); - arbitrationPolicySP = ArbitrationPolicySP( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(ArbitrationPolicySP.initialize, (address(governance)))) - ); - impl = address(0); - _postdeploy(contractKey, address(arbitrationPolicySP)); - - contractKey = "RoyaltyPolicyLAP"; - _predeploy(contractKey); - impl = address(new RoyaltyPolicyLAP(address(royaltyModule), address(licensingModule))); - - royaltyPolicyLAP = RoyaltyPolicyLAP( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(RoyaltyPolicyLAP.initialize, (address(governance)))) - ); - impl = address(0); - _postdeploy(contractKey, address(royaltyPolicyLAP)); - - _predeploy("PILicenseTemplate"); - impl = address( - new PILicenseTemplate( - address(accessController), - address(ipAccountRegistry), - address(licenseRegistry), - address(royaltyModule), - address(licenseToken) - ) - ); - piLt = PILicenseTemplate( - TestProxyHelper.deployUUPSProxy( - impl, - abi.encodeCall( - PILicenseTemplate.initialize, - ("pil", "https://github.com/storyprotocol/protocol-core/blob/main/PIL-Beta-2024-02.pdf") - ) - ) - ); - impl = address(0); // Make sure we don't deploy wrong impl - _postdeploy("PILicenseTemplate", address(piLt)); - - // - // Mock Hooks - // - - contractKey = "MockTokenGatedHook"; - _predeploy(contractKey); - mockTokenGatedHook = new MockTokenGatedHook(); - _postdeploy(contractKey, address(mockTokenGatedHook)); - } - - function _predeploy(string memory contractKey) private view { - console2.log(string.concat("Deploying ", contractKey, "...")); - } - - function _postdeploy(string memory contractKey, address newAddress) private { - _writeAddress(contractKey, newAddress); - console2.log(string.concat(contractKey, " deployed to:"), newAddress); - } - - function _configureDeployment() private { - _configureMisc(); - _configureAccessController(); - _configureModuleRegistry(); - _configureRoyaltyRelated(); - _configureDisputeModule(); - _executeInteractions(); - coreMetadataViewModule.updateCoreMetadataModule(); - } - - function _configureMisc() private { - licenseRegistry.setDisputeModule(address(disputeModule)); - licenseRegistry.setLicensingModule(address(licensingModule)); - } - - function _configureAccessController() private { - accessController.setAddresses(address(ipAccountRegistry), address(moduleRegistry)); - } - - function _configureModuleRegistry() private { - moduleRegistry.registerModule(DISPUTE_MODULE_KEY, address(disputeModule)); - moduleRegistry.registerModule(LICENSING_MODULE_KEY, address(licensingModule)); - moduleRegistry.registerModule(ROYALTY_MODULE_KEY, address(royaltyModule)); - moduleRegistry.registerModule(TOKEN_WITHDRAWAL_MODULE_KEY, address(tokenWithdrawalModule)); - moduleRegistry.registerModule(CORE_METADATA_MODULE_KEY, address(coreMetadataModule)); - moduleRegistry.registerModule(CORE_METADATA_VIEW_MODULE_KEY, address(coreMetadataViewModule)); - - } - - function _configureRoyaltyRelated() private { - royaltyModule.setLicensingModule(address(licensingModule)); - royaltyModule.setDisputeModule(address(disputeModule)); - // whitelist - royaltyModule.whitelistRoyaltyPolicy(address(royaltyPolicyLAP), true); - royaltyModule.whitelistRoyaltyToken(address(erc20), true); - // policy - royaltyPolicyLAP.setSnapshotInterval(7 days); - } - - function _configureDisputeModule() private { - // whitelist - disputeModule.whitelistDisputeTag("PLAGIARISM", true); - disputeModule.whitelistArbitrationPolicy(address(arbitrationPolicySP), true); - address arbitrationRelayer = deployer; - disputeModule.whitelistArbitrationRelayer(address(arbitrationPolicySP), arbitrationRelayer, true); - - disputeModule.setBaseArbitrationPolicy(address(arbitrationPolicySP)); - } - - function _executeInteractions() private { - for (uint256 i = 1; i <= 5; i++) { - erc721.mintId(deployer, i); - } - erc721.mintId(deployer, 100); - erc721.mintId(deployer, 101); - erc721.mintId(deployer, 102); - erc721.mintId(deployer, 103); - erc721.mintId(deployer, 104); - erc721.mintId(deployer, 105); - erc20.mint(deployer, 100_000_000 ether); - - erc20.approve(address(arbitrationPolicySP), 1000 * ARBITRATION_PRICE); // 1000 * raising disputes - // For license/royalty payment, on both minting license and royalty distribution - erc20.approve(address(royaltyPolicyLAP), MAX_ROYALTY_APPROVAL); - - licenseRegistry.registerLicenseTemplate(address(piLt)); - templateAddrs["pil"] = address(piLt); - - accessController.setGlobalPermission( - address(ipAssetRegistry), - address(licensingModule), - bytes4(0x9f69e70d), - AccessPermission.ALLOW - ); - - accessController.setGlobalPermission( - address(ipAssetRegistry), - address(licenseRegistry), - bytes4(0), // wildcard - AccessPermission.ALLOW - ); - - accessController.setGlobalPermission( - address(ipAssetRegistry), - address(licenseRegistry), - bytes4(0), // wildcard - AccessPermission.ALLOW - ); - - /*/////////////////////////////////////////////////////////////// - CREATE POLICIES - ///////////////////////////////////////////////////////////////*/ - - // Policy ID 1 - policyIds["social_remixing"] = piLt.registerLicenseTerms(PILFlavors.nonCommercialSocialRemixing()); - - // Policy ID 2 - policyIds["pil_com_deriv_expensive"] = piLt.registerLicenseTerms( - PILTerms({ - transferable: true, - royaltyPolicy: address(royaltyPolicyLAP), - mintingFee: 1 ether, - expiration: 0, - commercialUse: true, - commercialAttribution: true, - commercializerChecker: address(mockTokenGatedHook), - commercializerCheckerData: abi.encode(address(erc721)), // use `erc721` as gated token - commercialRevShare: 100, - commercialRevCelling: 0, - derivativesAllowed: true, - derivativesAttribution: false, - derivativesApproval: false, - derivativesReciprocal: true, - derivativeRevCelling: 0, - currency: address(erc20) - }) - ); - - // Policy ID 3 - policyIds["pil_noncom_deriv_reciprocal"] = piLt.registerLicenseTerms( - PILTerms({ - transferable: false, - royaltyPolicy: address(0), - mintingFee: 0, - expiration: 0, - commercialUse: false, - commercialAttribution: false, - commercializerChecker: address(0), - commercializerCheckerData: "", - commercialRevShare: 0, - commercialRevCelling: 0, - derivativesAllowed: true, - derivativesAttribution: true, - derivativesApproval: false, - derivativesReciprocal: true, - derivativeRevCelling: 0, - currency: address(0) - }) - ); - - /*/////////////////////////////////////////////////////////////// - REGISTER IP ACCOUNTS - ///////////////////////////////////////////////////////////////*/ - - // IPAccount1 (tokenId 1) with no initial policy - vm.label(getIpId(erc721, 1), "IPAccount1"); - ipAcct[1] = ipAssetRegistry.register(address(erc721), 1); - disputeModule.setArbitrationPolicy(ipAcct[1], address(arbitrationPolicySP)); - - // IPAccount2 (tokenId 2) and attach policy "pil_noncom_deriv_reciprocal" - vm.label(getIpId(erc721, 2), "IPAccount2"); - ipAcct[2] = ipAssetRegistry.register(address(erc721), 2); - licensingModule.attachLicenseTerms(ipAcct[2], address(piLt), policyIds["pil_noncom_deriv_reciprocal"]); - - // wildcard allow - IIPAccount(payable(ipAcct[1])).execute( - address(accessController), - 0, - abi.encodeWithSignature( - "setPermission(address,address,address,bytes4,uint8)", - ipAcct[1], - deployer, - address(licenseRegistry), - bytes4(0), - AccessPermission.ALLOW - ) - ); - - /*/////////////////////////////////////////////////////////////// - ADD POLICIES TO IPACCOUNTS - ///////////////////////////////////////////////////////////////*/ - - // Add "pil_com_deriv_expensive" policy to IPAccount1 - licensingModule.attachLicenseTerms(ipAcct[1], address(piLt), policyIds["pil_com_deriv_expensive"]); - - /*/////////////////////////////////////////////////////////////// - LINK IPACCOUNTS TO PARENTS USING LICENSES - ///////////////////////////////////////////////////////////////*/ - - // Mint 2 license of policy "pil_com_deriv_expensive" on IPAccount1 - // Register derivative IP for NFT tokenId 3 - { - uint256[] memory licenseIds = new uint256[](1); - licenseIds[0] = licensingModule.mintLicenseTokens( - ipAcct[1], - address(piLt), - policyIds["pil_com_deriv_expensive"], - 2, - deployer, - "" - ); - - ipAcct[3] = getIpId(erc721, 3); - vm.label(ipAcct[3], "IPAccount3"); - - address ipId = ipAssetRegistry.register(address(erc721), 3); - licensingModule.registerDerivativeWithLicenseTokens(ipId, licenseIds, ""); - } - - // Mint 1 license of policy "pil_noncom_deriv_reciprocal" on IPAccount2 - // Register derivative IP for NFT tokenId 4 - { - uint256[] memory licenseIds = new uint256[](1); - licenseIds[0] = licensingModule.mintLicenseTokens( - ipAcct[2], - address(piLt), - policyIds["pil_noncom_deriv_reciprocal"], - 1, - deployer, - "" - ); - - ipAcct[4] = getIpId(erc721, 4); - vm.label(ipAcct[4], "IPAccount4"); - - ipAcct[4] = ipAssetRegistry.register(address(erc721), 4); - - licensingModule.registerDerivativeWithLicenseTokens(ipAcct[4], licenseIds, ""); - } - - // Multi-parent - { - ipAcct[5] = getIpId(erc721, 5); - vm.label(ipAcct[5], "IPAccount5"); - - uint256[] memory licenseIds = new uint256[](2); - licenseIds[0] = licensingModule.mintLicenseTokens( - ipAcct[1], - address(piLt), - policyIds["pil_com_deriv_expensive"], - 1, - deployer, - "" - ); - - licenseIds[1] = licensingModule.mintLicenseTokens( - ipAcct[3], // is child of ipAcct[1] - address(piLt), - policyIds["pil_com_deriv_expensive"], - 1, - deployer, - "" - ); - - address ipId = ipAssetRegistry.register(address(erc721), 5); - licensingModule.registerDerivativeWithLicenseTokens(ipId, licenseIds, ""); - } - - /*/////////////////////////////////////////////////////////////// - DISPUTE MODULE INTERACTIONS - ///////////////////////////////////////////////////////////////*/ - - // Say, IPAccount4 is accused of plagiarism by IPAccount2 - // Then, a judge (deployer in this example) settles as true. - // Then, the dispute is resolved. - { - uint256 disptueId = disputeModule.raiseDispute( - ipAcct[4], - string("evidence-url.com"), // TODO: https://dispute-evidence-url.com => string too long - "PLAGIARISM", - "" - ); - - disputeModule.setDisputeJudgement(disptueId, true, ""); - - disputeModule.resolveDispute(disptueId); - } - - // Say, IPAccount3 is accused of plagiarism by IPAccount1 - // But, IPAccount1 later cancels the dispute - { - uint256 disputeId = disputeModule.raiseDispute(ipAcct[3], string("https://example.com"), "PLAGIARISM", ""); - - disputeModule.cancelDispute(disputeId, bytes("Settled amicably")); - } - } - - function getIpId(MockERC721 mnft, uint256 tokenId) public view returns (address ipId) { - return ipAssetRegistry.ipAccount(block.chainid, address(mnft), tokenId); - } } diff --git a/script/foundry/utils/BroadcastManager.s.sol b/script/foundry/utils/BroadcastManager.s.sol index 281043d5..08e814cf 100644 --- a/script/foundry/utils/BroadcastManager.s.sol +++ b/script/foundry/utils/BroadcastManager.s.sol @@ -3,7 +3,8 @@ pragma solidity ^0.8.23; import { Script } from "forge-std/Script.sol"; -import { StringUtil } from "../../../script/foundry/utils/StringUtil.sol"; +import { StringUtil } from "./StringUtil.sol"; +import { MockERC20 } from "../../../test/foundry/mocks/token/MockERC20.sol"; contract BroadcastManager is Script { address public multisig; @@ -13,17 +14,17 @@ contract BroadcastManager is Script { uint256 deployerPrivateKey; if (block.chainid == 1) { // Tenderly mainnet fork deployerPrivateKey = vm.envUint("MAINNET_PRIVATEKEY"); - deployer = vm.envAddress("MAINNET_DEPLOYER_ADDRESS"); + deployer = vm.addr(deployerPrivateKey); multisig = vm.envAddress("MAINNET_MULTISIG_ADDRESS"); vm.startBroadcast(deployerPrivateKey); } else if (block.chainid == 11155111) { deployerPrivateKey = vm.envUint("SEPOLIA_PRIVATEKEY"); - deployer = vm.envAddress("SEPOLIA_DEPLOYER_ADDRESS"); + deployer = vm.addr(deployerPrivateKey); multisig = vm.envAddress("SEPOLIA_MULTISIG_ADDRESS"); vm.startBroadcast(deployerPrivateKey); } else if (block.chainid == 31337) { - multisig = address(0x456); - deployer = address(0x999); + require(deployer != address(0), "Deployer not set"); + multisig = vm.addr(0x987321); vm.startPrank(deployer); } else { revert("Unsupported chain"); diff --git a/script/foundry/utils/DeployHelper.sol b/script/foundry/utils/DeployHelper.sol new file mode 100644 index 00000000..32d37439 --- /dev/null +++ b/script/foundry/utils/DeployHelper.sol @@ -0,0 +1,373 @@ +/* solhint-disable no-console */ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.23; + +// external +import { UpgradeableBeacon } from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { console2 } from "forge-std/console2.sol"; +import { Script } from "forge-std/Script.sol"; +import { stdJson } from "forge-std/StdJson.sol"; +import { ERC6551Registry } from "erc6551/ERC6551Registry.sol"; + +// contracts +import { AccessController } from "contracts/access/AccessController.sol"; +import { IPAccountImpl } from "contracts/IPAccountImpl.sol"; +import { IIPAccount } from "contracts/interfaces/IIPAccount.sol"; +import { IRoyaltyPolicyLAP } from "contracts/interfaces/modules/royalty/policies/IRoyaltyPolicyLAP.sol"; +import { Governance } from "contracts/governance/Governance.sol"; +import { AccessPermission } from "contracts/lib/AccessPermission.sol"; +import { Errors } from "contracts/lib/Errors.sol"; +import { PILFlavors } from "contracts/lib/PILFlavors.sol"; +// solhint-disable-next-line max-line-length +import { DISPUTE_MODULE_KEY, ROYALTY_MODULE_KEY, LICENSING_MODULE_KEY, TOKEN_WITHDRAWAL_MODULE_KEY, CORE_METADATA_MODULE_KEY, CORE_METADATA_VIEW_MODULE_KEY } from "contracts/lib/modules/Module.sol"; +import { IPAccountRegistry } from "contracts/registries/IPAccountRegistry.sol"; +import { IPAssetRegistry } from "contracts/registries/IPAssetRegistry.sol"; +import { ModuleRegistry } from "contracts/registries/ModuleRegistry.sol"; +import { LicenseRegistry } from "contracts/registries/LicenseRegistry.sol"; +import { LicensingModule } from "contracts/modules/licensing/LicensingModule.sol"; +import { RoyaltyModule } from "contracts/modules/royalty/RoyaltyModule.sol"; +import { RoyaltyPolicyLAP } from "contracts/modules/royalty/policies/RoyaltyPolicyLAP.sol"; +import { DisputeModule } from "contracts/modules/dispute/DisputeModule.sol"; +import { ArbitrationPolicySP } from "contracts/modules/dispute/policies/ArbitrationPolicySP.sol"; +import { TokenWithdrawalModule } from "contracts/modules/external/TokenWithdrawalModule.sol"; +import { MODULE_TYPE_HOOK } from "contracts/lib/modules/Module.sol"; +import { IModule } from "contracts/interfaces/modules/base/IModule.sol"; +import { IHookModule } from "contracts/interfaces/modules/base/IHookModule.sol"; +import { IpRoyaltyVault } from "contracts/modules/royalty/policies/IpRoyaltyVault.sol"; +import { CoreMetadataModule } from "contracts/modules/metadata/CoreMetadataModule.sol"; +import { CoreMetadataViewModule } from "contracts/modules/metadata/CoreMetadataViewModule.sol"; +import { PILicenseTemplate, PILTerms } from "contracts/modules/licensing/PILicenseTemplate.sol"; +import { LicenseToken } from "contracts/LicenseToken.sol"; + +// script +import { StringUtil } from "./StringUtil.sol"; +import { BroadcastManager } from "./BroadcastManager.s.sol"; +import { StorageLayoutChecker } from "./upgrades/StorageLayoutCheck.s.sol"; +import { JsonDeploymentHandler } from "./JsonDeploymentHandler.s.sol"; + +// test +import { TestProxyHelper } from "test/foundry/utils/TestProxyHelper.sol"; + +contract DeployHelper is Script, BroadcastManager, JsonDeploymentHandler, StorageLayoutChecker { + using StringUtil for uint256; + using stdJson for string; + + ERC6551Registry internal immutable erc6551Registry; + IPAccountImpl internal ipAccountImpl; + + // Registry + IPAssetRegistry internal ipAssetRegistry; + LicenseRegistry internal licenseRegistry; + ModuleRegistry internal moduleRegistry; + + // Core Module + LicensingModule internal licensingModule; + DisputeModule internal disputeModule; + RoyaltyModule internal royaltyModule; + CoreMetadataModule internal coreMetadataModule; + + // External Module + CoreMetadataViewModule internal coreMetadataViewModule; + TokenWithdrawalModule internal tokenWithdrawalModule; + + // Policy + ArbitrationPolicySP internal arbitrationPolicySP; + RoyaltyPolicyLAP internal royaltyPolicyLAP; + UpgradeableBeacon internal ipRoyaltyVaultBeacon; + IpRoyaltyVault internal ipRoyaltyVaultImpl; + + // Access Control + Governance internal governance; + AccessController internal accessController; + + // License system + LicenseToken internal licenseToken; + PILicenseTemplate internal pilTemplate; + + // Token + ERC20 private immutable erc20; // keep private to avoid conflict with inheriting contracts + + // keep private to avoid conflict with inheriting contracts + uint256 private immutable ARBITRATION_PRICE; + uint256 private immutable MAX_ROYALTY_APPROVAL; + + // DeployHelper variable + bool private writeDeploys; + + constructor( + address erc6551Registry_, + address erc20_, + uint256 arbitrationPrice_, + uint256 maxRoyaltyApproval_ + ) JsonDeploymentHandler("main") { + erc6551Registry = ERC6551Registry(erc6551Registry_); + erc20 = ERC20(erc20_); + ARBITRATION_PRICE = arbitrationPrice_; + MAX_ROYALTY_APPROVAL = maxRoyaltyApproval_; + + /// @dev USDC addresses are fetched from + /// (mainnet) https://developers.circle.com/stablecoins/docs/usdc-on-main-networks + /// (testnet) https://developers.circle.com/stablecoins/docs/usdc-on-test-networks + if (block.chainid == 1) erc20 = ERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48); + else if (block.chainid == 11155111) erc20 = ERC20(0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238); + } + + /// @dev To use, run the following command (e.g. for Sepolia): + /// forge script script/foundry/deployment/Main.s.sol:Main --rpc-url $RPC_URL --broadcast --verify -vvvv + + function run( + address runDeployer, + bool configByMultisig, + bool runStorageLayoutCheck, + bool writeDeploys_ + ) public virtual { + writeDeploys = writeDeploys_; + + // This will run OZ storage layout check for all contracts. Requires --ffi flag. + if (runStorageLayoutCheck) super.run(); + + if (block.chainid == 31337) deployer = runDeployer; // set for local before _beginBroadcast + _beginBroadcast(); // BroadcastManager.s.sol + + _deployProtocolContracts(deployer); + if (!configByMultisig) { + _configureDeployment(); + } + + if (writeDeploys) _writeDeployment(); + _endBroadcast(); // BroadcastManager.s.sol + } + + function _deployProtocolContracts(address runDeployer) private { + require(address(erc20) != address(0), "Deploy: Asset Not Set"); + + string memory contractKey; + + // Core Protocol Contracts + + contractKey = "Governance"; + _predeploy(contractKey); + governance = new Governance(runDeployer); + _postdeploy(contractKey, address(governance)); + + contractKey = "AccessController"; + _predeploy(contractKey); + + address impl = address(new AccessController()); + accessController = AccessController( + TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(AccessController.initialize, address(governance))) + ); + impl = address(0); // Make sure we don't deploy wrong impl + _postdeploy(contractKey, address(accessController)); + + contractKey = "IPAccountImpl"; + _predeploy(contractKey); + ipAccountImpl = new IPAccountImpl(address(accessController)); + _postdeploy(contractKey, address(ipAccountImpl)); + + contractKey = "ModuleRegistry"; + _predeploy(contractKey); + impl = address(new ModuleRegistry()); + moduleRegistry = ModuleRegistry( + TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(ModuleRegistry.initialize, address(governance))) + ); + impl = address(0); // Make sure we don't deploy wrong impl + _postdeploy(contractKey, address(moduleRegistry)); + + contractKey = "IPAssetRegistry"; + _predeploy(contractKey); + ipAssetRegistry = new IPAssetRegistry(address(erc6551Registry), address(ipAccountImpl), address(governance)); + _postdeploy(contractKey, address(ipAssetRegistry)); + + IPAccountRegistry ipAccountRegistry = IPAccountRegistry(address(ipAssetRegistry)); + + contractKey = "RoyaltyModule"; + _predeploy(contractKey); + impl = address(new RoyaltyModule()); + royaltyModule = RoyaltyModule( + TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(RoyaltyModule.initialize, address(governance))) + ); + impl = address(0); + _postdeploy(contractKey, address(royaltyModule)); + + contractKey = "DisputeModule"; + _predeploy(contractKey); + impl = address(new DisputeModule(address(accessController), address(ipAssetRegistry))); + disputeModule = DisputeModule( + TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(DisputeModule.initialize, address(governance))) + ); + impl = address(0); + _postdeploy(contractKey, address(disputeModule)); + + contractKey = "LicenseRegistry"; + _predeploy(contractKey); + impl = address(new LicenseRegistry()); + licenseRegistry = LicenseRegistry( + TestProxyHelper.deployUUPSProxy( + impl, + abi.encodeCall( + LicenseRegistry.initialize, + ( + address(governance) + ) + ) + ) + ); + impl = address(0); // Make sure we don't deploy wrong impl + _postdeploy(contractKey, address(licenseRegistry)); + + contractKey = "LicenseToken"; + _predeploy(contractKey); + impl = address(new LicenseToken()); + licenseToken = LicenseToken( + TestProxyHelper.deployUUPSProxy( + impl, + abi.encodeCall( + LicenseToken.initialize, + ( + address(governance), + "https://github.com/storyprotocol/protocol-core/blob/main/assets/license-image.gif" + ) + ) + ) + ); + impl = address(0); + _postdeploy(contractKey, address(licenseToken)); + + contractKey = "LicensingModule"; + _predeploy(contractKey); + impl = address( + new LicensingModule( + address(accessController), + address(ipAccountRegistry), + address(royaltyModule), + address(licenseRegistry), + address(disputeModule), + address(licenseToken) + ) + ); + licensingModule = LicensingModule( + TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(LicensingModule.initialize, address(governance))) + ); + impl = address(0); // Make sure we don't deploy wrong impl + _postdeploy(contractKey, address(licensingModule)); + + // + // Story-specific Non-Core Contracts + // + + _predeploy("ArbitrationPolicySP"); + impl = address(new ArbitrationPolicySP(address(disputeModule), address(erc20), ARBITRATION_PRICE)); + arbitrationPolicySP = ArbitrationPolicySP( + TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(ArbitrationPolicySP.initialize, address(governance))) + ); + impl = address(0); + _postdeploy("ArbitrationPolicySP", address(arbitrationPolicySP)); + + _predeploy("RoyaltyPolicyLAP"); + impl = address(new RoyaltyPolicyLAP(address(royaltyModule), address(licensingModule))); + royaltyPolicyLAP = RoyaltyPolicyLAP( + TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(RoyaltyPolicyLAP.initialize, address(governance))) + ); + impl = address(0); + _postdeploy("RoyaltyPolicyLAP", address(royaltyPolicyLAP)); + + _predeploy("PILicenseTemplate"); + impl = address( + new PILicenseTemplate( + address(accessController), + address(ipAccountRegistry), + address(licenseRegistry), + address(royaltyModule), + address(licenseToken) + ) + ); + pilTemplate = PILicenseTemplate( + TestProxyHelper.deployUUPSProxy( + impl, + abi.encodeCall( + PILicenseTemplate.initialize, + ("pil", "https://github.com/storyprotocol/protocol-core/blob/main/PIL-Beta-2024-02.pdf") + ) + ) + ); + impl = address(0); + _postdeploy("PILicenseTemplate", address(pilTemplate)); + + _predeploy("IpRoyaltyVaultImpl"); + ipRoyaltyVaultImpl = new IpRoyaltyVault(address(royaltyPolicyLAP), address(disputeModule)); + _postdeploy("IpRoyaltyVaultImpl", address(ipRoyaltyVaultImpl)); + + _predeploy("IpRoyaltyVaultBeacon"); + ipRoyaltyVaultBeacon = new UpgradeableBeacon(address(ipRoyaltyVaultImpl), address(governance)); + _postdeploy("IpRoyaltyVaultBeacon", address(ipRoyaltyVaultBeacon)); + + _predeploy("CoreMetadataModule"); + coreMetadataModule = new CoreMetadataModule(address(accessController), address(ipAssetRegistry)); + _postdeploy("CoreMetadataModule", address(coreMetadataModule)); + + _predeploy("CoreMetadataViewModule"); + coreMetadataViewModule = new CoreMetadataViewModule(address(ipAssetRegistry), address(moduleRegistry)); + _postdeploy("CoreMetadataViewModule", address(coreMetadataViewModule)); + + _predeploy("TokenWithdrawalModule"); + tokenWithdrawalModule = new TokenWithdrawalModule(address(accessController), address(ipAccountRegistry)); + _postdeploy("TokenWithdrawalModule", address(tokenWithdrawalModule)); + } + + function _predeploy(string memory contractKey) private view { + if (writeDeploys) console2.log(string.concat("Deploying ", contractKey, "...")); + } + + function _postdeploy(string memory contractKey, address newAddress) private { + if (writeDeploys) { + _writeAddress(contractKey, newAddress); + console2.log(string.concat(contractKey, " deployed to:"), newAddress); + } + } + + function _configureDeployment() private { + IPAccountRegistry ipAccountRegistry = IPAccountRegistry(address(ipAssetRegistry)); + + // Module Registry + moduleRegistry.registerModule(DISPUTE_MODULE_KEY, address(disputeModule)); + moduleRegistry.registerModule(LICENSING_MODULE_KEY, address(licensingModule)); + moduleRegistry.registerModule(ROYALTY_MODULE_KEY, address(royaltyModule)); + moduleRegistry.registerModule(CORE_METADATA_MODULE_KEY, address(coreMetadataModule)); + moduleRegistry.registerModule(CORE_METADATA_VIEW_MODULE_KEY, address(coreMetadataViewModule)); + moduleRegistry.registerModule(TOKEN_WITHDRAWAL_MODULE_KEY, address(tokenWithdrawalModule)); + + // License Registry + licenseRegistry.setDisputeModule(address(disputeModule)); + licenseRegistry.setLicensingModule(address(licensingModule)); + + // License Token + licenseToken.setDisputeModule(address(disputeModule)); + licenseToken.setLicensingModule(address(licensingModule)); + + // Access Controller + accessController.setAddresses(address(ipAccountRegistry), address(moduleRegistry)); + + // Royalty Module and SP Royalty Policy + royaltyModule.setLicensingModule(address(licensingModule)); + royaltyModule.setDisputeModule(address(disputeModule)); + royaltyModule.whitelistRoyaltyPolicy(address(royaltyPolicyLAP), true); + royaltyModule.whitelistRoyaltyToken(address(erc20), true); + royaltyPolicyLAP.setSnapshotInterval(7 days); + royaltyPolicyLAP.setIpRoyaltyVaultBeacon(address(ipRoyaltyVaultBeacon)); + + // Dispute Module and SP Dispute Policy + address arbitrationRelayer = deployer; + disputeModule.whitelistDisputeTag("PLAGIARISM", true); + disputeModule.whitelistArbitrationPolicy(address(arbitrationPolicySP), true); + disputeModule.whitelistArbitrationRelayer(address(arbitrationPolicySP), arbitrationRelayer, true); + disputeModule.setBaseArbitrationPolicy(address(arbitrationPolicySP)); + + // Core Metadata Module + coreMetadataViewModule.updateCoreMetadataModule(); + + // License Template + licenseRegistry.registerLicenseTemplate(address(pilTemplate)); + } +} diff --git a/script/foundry/utils/JsonDeploymentHandler.s.sol b/script/foundry/utils/JsonDeploymentHandler.s.sol index 36f4d701..88c47472 100644 --- a/script/foundry/utils/JsonDeploymentHandler.s.sol +++ b/script/foundry/utils/JsonDeploymentHandler.s.sol @@ -10,11 +10,12 @@ contract JsonDeploymentHandler is Script { using StringUtil for uint256; using stdJson for string; - string output; - string readJson; - string chainId; - string key; - string internalKey = "key"; + // keep all variables private to avoid conflicts + string private output; + string private readJson; + string private chainId; + string private key; + string private internalKey = "key"; constructor(string memory _key) { chainId = (block.chainid).toString(); diff --git a/test/foundry/IPAccount.t.sol b/test/foundry/IPAccount.t.sol index 1659f008..b3facd22 100644 --- a/test/foundry/IPAccount.t.sol +++ b/test/foundry/IPAccount.t.sol @@ -14,10 +14,12 @@ contract IPAccountTest is BaseTest { function setUp() public override { super.setUp(); - deployConditionally(); - postDeploymentSetup(); module = new MockModule(address(ipAssetRegistry), address(moduleRegistry), "MockModule"); + + vm.startPrank(u.admin); // used twice, name() and registerModule() + moduleRegistry.registerModule(module.name(), address(module)); + vm.stopPrank(); } function test_IPAccount_Idempotency() public { diff --git a/test/foundry/IPAccountMetaTx.t.sol b/test/foundry/IPAccountMetaTx.t.sol index 13410026..3faf686a 100644 --- a/test/foundry/IPAccountMetaTx.t.sol +++ b/test/foundry/IPAccountMetaTx.t.sol @@ -25,10 +25,7 @@ contract IPAccountMetaTxTest is BaseTest { function setUp() public override { super.setUp(); - buildDeployAccessCondition(DeployAccessCondition({ accessController: true, governance: false })); - buildDeployRegistryCondition(DeployRegistryCondition({ moduleRegistry: true, licenseRegistry: false })); - deployConditionally(); - postDeploymentSetup(); + ownerPrivateKey = 0xA11111; callerPrivateKey = 0xB22222; owner = vm.addr(ownerPrivateKey); diff --git a/test/foundry/IPAccountStorage.t.sol b/test/foundry/IPAccountStorage.t.sol index 0048e4df..6bba7c0d 100644 --- a/test/foundry/IPAccountStorage.t.sol +++ b/test/foundry/IPAccountStorage.t.sol @@ -12,8 +12,6 @@ contract IPAccountStorageTest is BaseTest { function setUp() public override { super.setUp(); - deployConditionally(); - postDeploymentSetup(); module = new MockModule(address(ipAssetRegistry), address(moduleRegistry), "MockModule"); diff --git a/test/foundry/IPAccountStorageOps.t.sol b/test/foundry/IPAccountStorageOps.t.sol index 80ac39d3..8478e744 100644 --- a/test/foundry/IPAccountStorageOps.t.sol +++ b/test/foundry/IPAccountStorageOps.t.sol @@ -17,8 +17,6 @@ contract IPAccountStorageOpsTest is BaseTest { function setUp() public override { super.setUp(); - deployConditionally(); - postDeploymentSetup(); module = new MockModule(address(ipAssetRegistry), address(moduleRegistry), "MockModule"); diff --git a/test/foundry/access/AccessControlled.t.sol b/test/foundry/access/AccessControlled.t.sol index f7c66922..2e5fc575 100644 --- a/test/foundry/access/AccessControlled.t.sol +++ b/test/foundry/access/AccessControlled.t.sol @@ -17,9 +17,6 @@ contract AccessControlledTest is BaseTest { function setUp() public override { super.setUp(); - buildDeployAccessCondition(DeployAccessCondition({ accessController: true, governance: true })); - deployConditionally(); - postDeploymentSetup(); mockNFT.mintId(owner, tokenId); address deployedAccount = ipAccountRegistry.registerIpAccount(block.chainid, address(mockNFT), tokenId); @@ -31,6 +28,8 @@ contract AccessControlledTest is BaseTest { address(moduleRegistry), "MockAccessControlledModule" ); + + vm.prank(u.admin); moduleRegistry.registerModule("MockAccessControlledModule", address(mockModule)); } diff --git a/test/foundry/access/AccessController.t.sol b/test/foundry/access/AccessController.t.sol index a39449ab..25fb6301 100644 --- a/test/foundry/access/AccessController.t.sol +++ b/test/foundry/access/AccessController.t.sol @@ -4,8 +4,6 @@ pragma solidity 0.8.23; import { IIPAccount } from "../../../contracts/interfaces/IIPAccount.sol"; import { AccessPermission } from "../../../contracts/lib/AccessPermission.sol"; import { Errors } from "../../../contracts/lib/Errors.sol"; -import { TOKEN_WITHDRAWAL_MODULE_KEY } from "../../../contracts/lib/modules/Module.sol"; -import { TokenWithdrawalModule } from "../../../contracts/modules/external/TokenWithdrawalModule.sol"; import { MockModule } from "../mocks/module/MockModule.sol"; import { MockOrchestratorModule } from "../mocks/module/MockOrchestratorModule.sol"; @@ -24,15 +22,15 @@ contract AccessControllerTest is BaseTest { function setUp() public override { super.setUp(); - buildDeployAccessCondition(DeployAccessCondition({ accessController: true, governance: true })); - deployConditionally(); - postDeploymentSetup(); mockNFT.mintId(owner, tokenId); address deployedAccount = ipAccountRegistry.registerIpAccount(block.chainid, address(mockNFT), tokenId); ipAccount = IIPAccount(payable(deployedAccount)); mockModule = new MockModule(address(ipAccountRegistry), address(moduleRegistry), "MockModule"); + + vm.prank(u.admin); + moduleRegistry.registerModule("MockModule", address(mockModule)); } // test owner can set permission @@ -46,7 +44,6 @@ contract AccessControllerTest is BaseTest { // mock orchestration? function test_AccessController_ipAccountOwnerSetPermission() public { - moduleRegistry.registerModule("MockModule", address(mockModule)); address signer = vm.addr(2); vm.prank(owner); ipAccount.execute( @@ -79,7 +76,6 @@ contract AccessControllerTest is BaseTest { } function test_AccessController_revert_NonOwnerCannotSetPermission() public { - moduleRegistry.registerModule("MockModule", address(mockModule)); address signer = vm.addr(2); address nonOwner = vm.addr(3); vm.prank(nonOwner); @@ -107,7 +103,6 @@ contract AccessControllerTest is BaseTest { } function test_AccessController_revert_directSetPermission() public { - moduleRegistry.registerModule("MockModule", address(mockModule)); address signer = vm.addr(2); vm.prank(address(ipAccount)); @@ -165,7 +160,6 @@ contract AccessControllerTest is BaseTest { } function test_AccessController_revert_checkPermission() public { - moduleRegistry.registerModule("MockModule", address(mockModule)); address signer = vm.addr(2); vm.prank(owner); ipAccount.execute( @@ -204,7 +198,6 @@ contract AccessControllerTest is BaseTest { } function test_AccessController_functionPermissionWildcardAllow() public { - moduleRegistry.registerModule("MockModule", address(mockModule)); address signer = vm.addr(2); vm.prank(owner); ipAccount.execute( @@ -242,7 +235,6 @@ contract AccessControllerTest is BaseTest { } function test_AccessController_functionPermissionWildcardDeny() public { - moduleRegistry.registerModule("MockModule", address(mockModule)); address signer = vm.addr(2); vm.prank(owner); ipAccount.execute( @@ -288,7 +280,6 @@ contract AccessControllerTest is BaseTest { } function test_AccessController_toAddressPermissionWildcardAllow() public { - moduleRegistry.registerModule("MockModule", address(mockModule)); address signer = vm.addr(2); vm.prank(owner); ipAccount.execute( @@ -325,7 +316,6 @@ contract AccessControllerTest is BaseTest { } function test_AccessController_toAddressPermissionWildcardDeny() public { - moduleRegistry.registerModule("MockModule", address(mockModule)); address signer = vm.addr(2); vm.prank(owner); ipAccount.execute( @@ -371,7 +361,6 @@ contract AccessControllerTest is BaseTest { } function test_AccessController_overrideFunctionWildcard_allowOverrideDeny() public { - moduleRegistry.registerModule("MockModule", address(mockModule)); address signer = vm.addr(2); vm.prank(owner); ipAccount.execute( @@ -423,7 +412,6 @@ contract AccessControllerTest is BaseTest { } function test_AccessController_overrideFunctionWildcard_DenyOverrideAllow() public { - moduleRegistry.registerModule("MockModule", address(mockModule)); address signer = vm.addr(2); vm.prank(owner); ipAccount.execute( @@ -483,7 +471,6 @@ contract AccessControllerTest is BaseTest { } function test_AccessController_overrideToAddressWildcard_allowOverrideDeny() public { - moduleRegistry.registerModule("MockModule", address(mockModule)); address signer = vm.addr(2); vm.prank(owner); ipAccount.execute( @@ -535,7 +522,6 @@ contract AccessControllerTest is BaseTest { } function test_AccessController_overrideToAddressWildcard_DenyOverrideAllow() public { - moduleRegistry.registerModule("MockModule", address(mockModule)); address signer = vm.addr(2); vm.prank(owner); ipAccount.execute( @@ -595,7 +581,6 @@ contract AccessControllerTest is BaseTest { } function test_AccessController_functionWildcardOverrideToAddressWildcard_allowOverrideDeny() public { - moduleRegistry.registerModule("MockModule", address(mockModule)); address signer = vm.addr(2); vm.prank(owner); ipAccount.execute( @@ -652,7 +637,6 @@ contract AccessControllerTest is BaseTest { } function test_AccessController_functionWildcardOverrideToAddressWildcard_denyOverrideAllow() public { - moduleRegistry.registerModule("MockModule", address(mockModule)); address signer = vm.addr(2); vm.prank(owner); ipAccount.execute( @@ -717,8 +701,6 @@ contract AccessControllerTest is BaseTest { } function test_AccessController_ipAccountOwnerCanCallAnyModuleWithoutPermission() public { - moduleRegistry.registerModule("MockModule", address(mockModule)); - vm.prank(owner); bytes memory result = ipAccount.execute( address(mockModule), @@ -729,12 +711,12 @@ contract AccessControllerTest is BaseTest { } function test_AccessController_moduleCallAnotherModuleViaIpAccount() public { - moduleRegistry.registerModule("MockModule", address(mockModule)); MockModule anotherModule = new MockModule( address(ipAccountRegistry), address(moduleRegistry), "AnotherMockModule" ); + vm.prank(u.admin); moduleRegistry.registerModule("AnotherMockModule", address(anotherModule)); vm.prank(owner); @@ -761,6 +743,7 @@ contract AccessControllerTest is BaseTest { } function test_AccessController_OrchestratorModuleCallIpAccount() public { + vm.startPrank(u.admin); MockOrchestratorModule mockOrchestratorModule = new MockOrchestratorModule( address(ipAccountRegistry), address(moduleRegistry) @@ -787,6 +770,7 @@ contract AccessControllerTest is BaseTest { "Module3WithoutPermission" ); moduleRegistry.registerModule("Module3WithoutPermission", address(module3WithoutPermission)); + vm.stopPrank(); vm.prank(owner); // orchestrator can call any modules through ipAccount @@ -808,6 +792,7 @@ contract AccessControllerTest is BaseTest { } function test_AccessController_revert_OrchestratorModuleCallIpAccountLackSomeModulePermission() public { + vm.startPrank(u.admin); MockOrchestratorModule mockOrchestratorModule = new MockOrchestratorModule( address(ipAccountRegistry), address(moduleRegistry) @@ -834,6 +819,7 @@ contract AccessControllerTest is BaseTest { "Module3WithoutPermission" ); moduleRegistry.registerModule("Module3WithoutPermission", address(module3WithoutPermission)); + vm.stopPrank(); vm.prank(owner); // orchestrator can call any modules through ipAccount @@ -879,6 +865,7 @@ contract AccessControllerTest is BaseTest { } function test_AccessController_OrchestratorModuleWithGlobalPermission() public { + vm.startPrank(u.admin); MockOrchestratorModule mockOrchestratorModule = new MockOrchestratorModule( address(ipAccountRegistry), address(moduleRegistry) @@ -898,6 +885,7 @@ contract AccessControllerTest is BaseTest { "Module2WithPermission" ); moduleRegistry.registerModule("Module2WithPermission", address(module2WithPermission)); + vm.stopPrank(); vm.prank(u.admin); accessController.setGlobalPermission( @@ -942,7 +930,6 @@ contract AccessControllerTest is BaseTest { } function test_AccessController_ipAccountOwnerSetBatchPermissions() public { - moduleRegistry.registerModule("MockModule", address(mockModule)); address signer = vm.addr(2); AccessPermission.Permission[] memory permissionList = new AccessPermission.Permission[](3); @@ -1036,7 +1023,6 @@ contract AccessControllerTest is BaseTest { } function test_AccessController_revert_NonIpAccountOwnerSetBatchPermissions() public { - moduleRegistry.registerModule("MockModule", address(mockModule)); address signer = vm.addr(2); AccessPermission.Permission[] memory permissionList = new AccessPermission.Permission[](3); @@ -1081,7 +1067,6 @@ contract AccessControllerTest is BaseTest { } function test_AccessController_revert_setBatchPermissionsWithZeroIPAccountAddress() public { - moduleRegistry.registerModule("MockModule", address(mockModule)); address signer = vm.addr(2); AccessPermission.Permission[] memory permissionList = new AccessPermission.Permission[](3); @@ -1117,7 +1102,6 @@ contract AccessControllerTest is BaseTest { } function test_AccessController_revert_setBatchPermissionsWithZeroSignerAddress() public { - moduleRegistry.registerModule("MockModule", address(mockModule)); address signer = vm.addr(2); AccessPermission.Permission[] memory permissionList = new AccessPermission.Permission[](3); @@ -1153,7 +1137,6 @@ contract AccessControllerTest is BaseTest { } function test_AccessController_revert_setBatchPermissionsWithInvalidIPAccount() public { - moduleRegistry.registerModule("MockModule", address(mockModule)); address signer = vm.addr(2); AccessPermission.Permission[] memory permissionList = new AccessPermission.Permission[](3); @@ -1192,7 +1175,6 @@ contract AccessControllerTest is BaseTest { } function test_AccessController_revert_setBatchPermissionsWithInvalidPermission() public { - moduleRegistry.registerModule("MockModule", address(mockModule)); address signer = vm.addr(2); AccessPermission.Permission[] memory permissionList = new AccessPermission.Permission[](3); @@ -1229,7 +1211,6 @@ contract AccessControllerTest is BaseTest { } function test_AccessController_revert_setBatchPermissionsButCallerisNotIPAccount() public { - moduleRegistry.registerModule("MockModule", address(mockModule)); address signer = vm.addr(2); AccessPermission.Permission[] memory permissionList = new AccessPermission.Permission[](3); @@ -1262,7 +1243,6 @@ contract AccessControllerTest is BaseTest { // test permission was unset after transfer NFT to another account function test_AccessController_NFTTransfer() public { - moduleRegistry.registerModule("MockModule", address(mockModule)); address signer = vm.addr(2); vm.prank(owner); ipAccount.execute( @@ -1301,7 +1281,6 @@ contract AccessControllerTest is BaseTest { // test permission check failure after transfer NFT to another account function test_AccessController_revert_NFTTransferCheckPermissionFailure() public { - moduleRegistry.registerModule("MockModule", address(mockModule)); address signer = vm.addr(2); vm.prank(owner); ipAccount.execute( @@ -1344,7 +1323,6 @@ contract AccessControllerTest is BaseTest { // test permission still exist after transfer NFT back function test_AccessController_NFTTransferBack() public { - moduleRegistry.registerModule("MockModule", address(mockModule)); address signer = vm.addr(2); vm.prank(owner); ipAccount.execute( @@ -1397,7 +1375,6 @@ contract AccessControllerTest is BaseTest { // test permission check still pass after transfer NFT back function test_AccessController_NFTTransferBackCheckPermission() public { - moduleRegistry.registerModule("MockModule", address(mockModule)); address signer = vm.addr(2); vm.prank(owner); ipAccount.execute( @@ -1450,7 +1427,6 @@ contract AccessControllerTest is BaseTest { // test permission was unset after burn NFT function test_AccessController_NFTBurn() public { - moduleRegistry.registerModule("MockModule", address(mockModule)); address signer = vm.addr(2); vm.prank(owner); ipAccount.execute( @@ -1487,7 +1463,6 @@ contract AccessControllerTest is BaseTest { // test permission check failed after burn NFT function test_AccessController_revert_NFTBurnCheckPermissionFailure() public { - moduleRegistry.registerModule("MockModule", address(mockModule)); address signer = vm.addr(2); vm.prank(owner); ipAccount.execute( @@ -1527,11 +1502,6 @@ contract AccessControllerTest is BaseTest { address anotherAccount = vm.addr(3); - TokenWithdrawalModule tokenWithdrawalModule = new TokenWithdrawalModule( - address(accessController), - address(ipAccountRegistry) - ); - moduleRegistry.registerModule(TOKEN_WITHDRAWAL_MODULE_KEY, address(tokenWithdrawalModule)); vm.prank(owner); ipAccount.execute( address(accessController), @@ -1567,11 +1537,6 @@ contract AccessControllerTest is BaseTest { address anotherAccount = vm.addr(3); - TokenWithdrawalModule tokenWithdrawalModule = new TokenWithdrawalModule( - address(accessController), - address(ipAccountRegistry) - ); - moduleRegistry.registerModule(TOKEN_WITHDRAWAL_MODULE_KEY, address(tokenWithdrawalModule)); vm.prank(owner); ipAccount.execute( address(accessController), @@ -1605,11 +1570,6 @@ contract AccessControllerTest is BaseTest { address anotherAccount = vm.addr(3); - TokenWithdrawalModule tokenWithdrawalModule = new TokenWithdrawalModule( - address(accessController), - address(ipAccountRegistry) - ); - moduleRegistry.registerModule(TOKEN_WITHDRAWAL_MODULE_KEY, address(tokenWithdrawalModule)); vm.prank(owner); ipAccount.execute( address(accessController), diff --git a/test/foundry/governance/Governance.t.sol b/test/foundry/governance/Governance.t.sol index 5e03632b..956a877c 100644 --- a/test/foundry/governance/Governance.t.sol +++ b/test/foundry/governance/Governance.t.sol @@ -21,10 +21,6 @@ contract GovernanceTest is BaseTest { function setUp() public override { super.setUp(); - buildDeployAccessCondition(DeployAccessCondition({ accessController: true, governance: true })); - buildDeployRegistryCondition(DeployRegistryCondition({ moduleRegistry: true, licenseRegistry: false })); - deployConditionally(); - postDeploymentSetup(); mockNFT.mintId(owner, tokenId); diff --git a/test/foundry/integration/BaseIntegration.t.sol b/test/foundry/integration/BaseIntegration.t.sol index 9bd62d28..3a543be4 100644 --- a/test/foundry/integration/BaseIntegration.t.sol +++ b/test/foundry/integration/BaseIntegration.t.sol @@ -20,16 +20,6 @@ contract BaseIntegration is BaseTest { using Strings for *; function setUp() public virtual override(BaseTest) { super.setUp(); - // deploy everything as real contracts - buildDeployAccessCondition(DeployAccessCondition({ governance: true, accessController: true })); - buildDeployRegistryCondition(DeployRegistryCondition({ licenseRegistry: true, moduleRegistry: true })); - buildDeployModuleCondition( - DeployModuleCondition({ disputeModule: true, royaltyModule: true, licensingModule: true }) - ); - buildDeployPolicyCondition(DeployPolicyCondition({ arbitrationPolicySP: true, royaltyPolicyLAP: true })); - - deployConditionally(); - postDeploymentSetup(); dealMockAssets(); diff --git a/test/foundry/integration/flows/disputes/Disputes.t.sol b/test/foundry/integration/flows/disputes/Disputes.t.sol index 4e7440db..eff1fcbd 100644 --- a/test/foundry/integration/flows/disputes/Disputes.t.sol +++ b/test/foundry/integration/flows/disputes/Disputes.t.sol @@ -17,7 +17,7 @@ contract Flows_Integration_Disputes is BaseIntegration { using Strings for *; mapping(uint256 tokenId => address ipAccount) internal ipAcct; - uint256 policyId; + uint256 internal policyId; function setUp() public override { super.setUp(); diff --git a/test/foundry/integration/flows/emergence-universe/EmergenceUniverse.t.sol b/test/foundry/integration/flows/emergence-universe/EmergenceUniverse.t.sol deleted file mode 100644 index 98ed53bb..00000000 --- a/test/foundry/integration/flows/emergence-universe/EmergenceUniverse.t.sol +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.23; - -import { Test } from "forge-std/Test.sol"; - -import { Users, UsersLib } from "test/foundry/utils/Users.t.sol"; - -contract Integration_Flow_EmergenceUniverse_Test is Test { - Users internal u; - - function setUp() public { - u = UsersLib.createMockUsers(vm); - } - - function test_IntegrationFlow_EmergenceUniverse() public {} -} diff --git a/test/foundry/integration/flows/emergence-universe/README.md b/test/foundry/integration/flows/emergence-universe/README.md deleted file mode 100644 index 73d0fe02..00000000 --- a/test/foundry/integration/flows/emergence-universe/README.md +++ /dev/null @@ -1,10 +0,0 @@ -Bob registers Skadi IPA via Emergence Policy -We can technically see this being an example of lazy deployment. For example, The resolver shows the Skadi image and other important metadata, but since nothing is being done with Skadi yet, the IPAccount is not yet deployed. (Optional) -Emergence sets some restrictions on what Skadi can do (lets say for example, NO commercial licensing EVER) -At this point, the IPAccount needs to be created in order to set restrictions/access control. -Bob registers Skadi IPA to Magma Policy. How do we know if it is compatible? What happens if it is? What happens if it isn’t? Use some example terms so we can flow through the terms part of the protocol. -Now Bob creates an LNFT of Skadi that Alice obtains, that LNFT stipulates some additional restrictions on top of Emergence’s. Say, anyone with the LNFT can create a derivative, but that derivative cannot allow other derivatives, aka the license tree needs to stop with that derivative and no further ones. How is this additional policy stored and distinguished from the EU policy? -Alice uses that LNFT to create Evil Skadi IPA, a derivative of Skadi IPA. How does this work? -Evil Skadi inherits the restrictions set by a) Emergence b) Magma (? or no?) and c) any additional restrictions/terms Bob has slapped onto the LNFT, such as the restriction from derivatives being made of Evil Skadi. -Evil Skadi generates revenue by selling collectible copies. How does this flow back to both Alice and Bob? -Evil Skadi is copied by Evil Alice without permission. People mistakenly think this is the authentic Evil Skadi made by normal Alice. Evil Skadi generated revenue. How does Evil Skadi get disputed? What happens to the revenue? \ No newline at end of file diff --git a/test/foundry/integration/flows/licensing/LicensingScenarios.t.sol b/test/foundry/integration/flows/licensing/LicensingScenarios.t.sol index 4115413e..c0c38e12 100644 --- a/test/foundry/integration/flows/licensing/LicensingScenarios.t.sol +++ b/test/foundry/integration/flows/licensing/LicensingScenarios.t.sol @@ -17,7 +17,7 @@ contract Licensing_Scenarios is BaseIntegration { using Strings for *; mapping(uint256 tokenId => address ipAccount) internal ipAcct; - uint256 nonCommRemixPoliciyId; + uint256 internal nonCommRemixPoliciyId; function setUp() public override { super.setUp(); diff --git a/test/foundry/integration/flows/royalty/Royalty.t.sol b/test/foundry/integration/flows/royalty/Royalty.t.sol index 262a8993..7b18fe7b 100644 --- a/test/foundry/integration/flows/royalty/Royalty.t.sol +++ b/test/foundry/integration/flows/royalty/Royalty.t.sol @@ -54,7 +54,7 @@ contract Flows_Integration_Disputes is BaseIntegration { { vm.startPrank(u.alice); - ipAcct[1] = _getIpId(mockNFT, 1); + ipAcct[1] = ipAccountRegistry.ipAccount(block.chainid, address(mockNFT), 1); vm.label(ipAcct[1], "IPAccount1"); registerIpAccount(mockNFT, 1, u.alice); @@ -67,7 +67,7 @@ contract Flows_Integration_Disputes is BaseIntegration { { vm.startPrank(u.bob); - ipAcct[2] = _getIpId(mockNFT, 2); + ipAcct[2] = ipAccountRegistry.ipAccount(block.chainid, address(mockNFT), 2); vm.label(ipAcct[2], "IPAccount2"); uint256 mintAmount = 3; @@ -98,7 +98,7 @@ contract Flows_Integration_Disputes is BaseIntegration { { vm.startPrank(u.carl); - ipAcct[3] = _getIpId(mockNFT, 3); + ipAcct[3] = ipAccountRegistry.ipAccount(block.chainid, address(mockNFT), 3); vm.label(ipAcct[3], "IPAccount3"); uint256 mintAmount = 1; diff --git a/test/foundry/mocks/policy/MockRoyaltyPolicyLAP.sol b/test/foundry/mocks/policy/MockRoyaltyPolicyLAP.sol new file mode 100644 index 00000000..f55cb0c9 --- /dev/null +++ b/test/foundry/mocks/policy/MockRoyaltyPolicyLAP.sol @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.23; + +import { IRoyaltyPolicyLAP } from "../../../../contracts/interfaces/modules/royalty/policies/IRoyaltyPolicyLAP.sol"; + +contract MockRoyaltyPolicyLAP is IRoyaltyPolicyLAP { + struct RoyaltyPolicyLAPStorage { + address ipRoyaltyVaultBeacon; + uint256 snapshotInterval; + mapping(address ipId => IRoyaltyPolicyLAP.LAPRoyaltyData) royaltyData; + } + + bytes32 private constant RoyaltyPolicyLAPStorageLocation = + 0x0c915ba68e2c4e37f19454bb13066f18f9db418fcefbf3c585b4b7d0fb0e0600; + + uint32 public constant TOTAL_RT_SUPPLY = 100000000; + uint256 public constant MAX_PARENTS = 100; + uint256 public constant MAX_ANCESTORS = 100; + address public constant LICENSING_MODULE = address(0); + address public constant ROYALTY_MODULE = address(0); + + constructor() {} + + function setSnapshotInterval(uint256 timestampInterval) public { + RoyaltyPolicyLAPStorage storage $ = _getRoyaltyPolicyLAPStorage(); + $.snapshotInterval = timestampInterval; + } + + function setIpRoyaltyVaultBeacon(address beacon) public { + RoyaltyPolicyLAPStorage storage $ = _getRoyaltyPolicyLAPStorage(); + $.ipRoyaltyVaultBeacon = beacon; + } + + function onLicenseMinting(address ipId, bytes calldata licenseData, bytes calldata externalData) external {} + + function onLinkToParents( + address ipId, + address[] calldata parentIpIds, + bytes[] memory licenseData, + bytes calldata externalData + ) external {} + + function onRoyaltyPayment(address caller, address ipId, address token, uint256 amount) external {} + + function getRoyaltyData( + address ipId + ) external view returns (bool, address, uint32, address[] memory, uint32[] memory) { + RoyaltyPolicyLAPStorage storage $ = _getRoyaltyPolicyLAPStorage(); + IRoyaltyPolicyLAP.LAPRoyaltyData memory data = $.royaltyData[ipId]; + return ( + data.isUnlinkableToParents, + data.ipRoyaltyVault, + data.royaltyStack, + data.ancestorsAddresses, + data.ancestorsRoyalties + ); + } + + function getSnapshotInterval() external view returns (uint256) { + RoyaltyPolicyLAPStorage storage $ = _getRoyaltyPolicyLAPStorage(); + return $.snapshotInterval; + } + + function getIpRoyaltyVaultBeacon() external view returns (address) { + RoyaltyPolicyLAPStorage storage $ = _getRoyaltyPolicyLAPStorage(); + return $.ipRoyaltyVaultBeacon; + } + + function _getRoyaltyPolicyLAPStorage() private pure returns (RoyaltyPolicyLAPStorage storage $) { + assembly { + $.slot := RoyaltyPolicyLAPStorageLocation + } + } +} diff --git a/test/foundry/modules/ModuleBase.t.sol b/test/foundry/modules/ModuleBase.t.sol index b5deeffe..339f908f 100644 --- a/test/foundry/modules/ModuleBase.t.sol +++ b/test/foundry/modules/ModuleBase.t.sol @@ -15,9 +15,6 @@ abstract contract ModuleBaseTest is BaseTest { function setUp() public virtual override(BaseTest) { super.setUp(); - deployConditionally(); - postDeploymentSetup(); - baseModule = IModule(_deployModule()); } diff --git a/test/foundry/modules/dispute/ArbitrationPolicySP.t.sol b/test/foundry/modules/dispute/ArbitrationPolicySP.t.sol index e7fb3992..bcc2be82 100644 --- a/test/foundry/modules/dispute/ArbitrationPolicySP.t.sol +++ b/test/foundry/modules/dispute/ArbitrationPolicySP.t.sol @@ -21,12 +21,6 @@ contract TestArbitrationPolicySP is BaseTest { function setUp() public override { super.setUp(); - buildDeployModuleCondition( - DeployModuleCondition({ disputeModule: true, royaltyModule: false, licensingModule: false }) - ); - buildDeployPolicyCondition(DeployPolicyCondition({ arbitrationPolicySP: true, royaltyPolicyLAP: true })); - deployConditionally(); - postDeploymentSetup(); arbitrationRelayer = u.admin; diff --git a/test/foundry/modules/dispute/DisputeModule.t.sol b/test/foundry/modules/dispute/DisputeModule.t.sol index e650171d..1cd987fc 100644 --- a/test/foundry/modules/dispute/DisputeModule.t.sol +++ b/test/foundry/modules/dispute/DisputeModule.t.sol @@ -42,22 +42,15 @@ contract DisputeModuleTest is BaseTest { function setUp() public override { super.setUp(); - buildDeployModuleCondition( - DeployModuleCondition({ disputeModule: true, royaltyModule: false, licensingModule: false }) - ); - buildDeployPolicyCondition(DeployPolicyCondition({ arbitrationPolicySP: true, royaltyPolicyLAP: true })); - - deployConditionally(); - postDeploymentSetup(); arbitrationRelayer = u.admin; USDC.mint(ipAccount1, 1000 * 10 ** 6); // second arbitration policy - address impl = address(new ArbitrationPolicySP(getDisputeModule(), address(USDC), ARBITRATION_PRICE)); + address impl = address(new ArbitrationPolicySP(address(disputeModule), address(USDC), ARBITRATION_PRICE)); arbitrationPolicySP2 = ArbitrationPolicySP( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(ArbitrationPolicySP.initialize, (getGovernance()))) + TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(ArbitrationPolicySP.initialize, address(governance))) ); vm.startPrank(u.admin); diff --git a/test/foundry/modules/external/TokenWithdrawalModule.t.sol b/test/foundry/modules/external/TokenWithdrawalModule.t.sol index 171a5841..b52a4220 100644 --- a/test/foundry/modules/external/TokenWithdrawalModule.t.sol +++ b/test/foundry/modules/external/TokenWithdrawalModule.t.sol @@ -7,9 +7,7 @@ import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; // contracts import { IIPAccount } from "../../../../contracts/interfaces/IIPAccount.sol"; import { AccessPermission } from "../../../../contracts/lib/AccessPermission.sol"; -import { TokenWithdrawalModule } from "../../../../contracts/modules/external/TokenWithdrawalModule.sol"; import { Errors } from "../../../../contracts/lib/Errors.sol"; -import { TOKEN_WITHDRAWAL_MODULE_KEY } from "../../../../contracts/lib/modules/Module.sol"; // test import { MockERC20 } from "../../mocks/token/MockERC20.sol"; @@ -24,21 +22,15 @@ contract TokenWithdrawalModuleTest is BaseTest { MockERC721 private tErc721 = new MockERC721("MockERC721"); MockERC1155 private tErc1155 = new MockERC1155("uri"); - TokenWithdrawalModule private tokenWithdrawalModule; - IIPAccount private ipAcct1; IIPAccount private ipAcct2; - uint256 mintAmount20 = 100 * 10 ** tErc20.decimals(); + uint256 private mintAmount20 = 100 * 10 ** tErc20.decimals(); - address randomFrontend = address(0x123); + address private randomFrontend = address(0x123); function setUp() public override { super.setUp(); - buildDeployAccessCondition(DeployAccessCondition({ accessController: true, governance: true })); - buildDeployRegistryCondition(DeployRegistryCondition({ licenseRegistry: false, moduleRegistry: true })); - deployConditionally(); - postDeploymentSetup(); // Create IPAccounts (Alice is the owner) mockNFT.mintId(alice, 1); @@ -49,11 +41,6 @@ contract TokenWithdrawalModuleTest is BaseTest { vm.label(address(ipAcct1), "IPAccount1"); vm.label(address(ipAcct2), "IPAccount2"); - - tokenWithdrawalModule = new TokenWithdrawalModule(address(accessController), address(ipAccountRegistry)); - - vm.prank(u.admin); - moduleRegistry.registerModule(TOKEN_WITHDRAWAL_MODULE_KEY, address(tokenWithdrawalModule)); } modifier testERC20_mintToIpAcct1() { diff --git a/test/foundry/modules/licensing/LicensingModule.t.sol b/test/foundry/modules/licensing/LicensingModule.t.sol index 84d79725..b623ee96 100644 --- a/test/foundry/modules/licensing/LicensingModule.t.sol +++ b/test/foundry/modules/licensing/LicensingModule.t.sol @@ -5,20 +5,22 @@ pragma solidity 0.8.23; import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; // contracts -import { IIPAccount } from "contracts/interfaces/IIPAccount.sol"; -import { AccessPermission } from "contracts/lib/AccessPermission.sol"; -import { Errors } from "contracts/lib/Errors.sol"; -import { Licensing } from "contracts/lib/Licensing.sol"; -import { RegisterPILPolicyParams } from "contracts/interfaces/modules/licensing/IPILPolicyFrameworkManager.sol"; -import { PILPolicy } from "contracts/modules/licensing/PILPolicyFrameworkManager.sol"; +import { IIPAccount } from "../../../../contracts/interfaces/IIPAccount.sol"; +import { AccessPermission } from "../../../../contracts/lib/AccessPermission.sol"; +import { Errors } from "../../../../contracts/lib/Errors.sol"; +import { Licensing } from "../../../../contracts/lib/Licensing.sol"; +// solhint-disable-next-line max-line-length +import { RegisterPILPolicyParams } from "../../../../contracts/interfaces/modules/licensing/IPILPolicyFrameworkManager.sol"; +import { PILPolicy } from "../../../../contracts/modules/licensing/PILPolicyFrameworkManager.sol"; +import { IRoyaltyPolicyLAP } from "../../../../contracts/interfaces/modules/royalty/policies/IRoyaltyPolicyLAP.sol"; // test // solhint-disable-next-line max-line-length -import { MockPolicyFrameworkManager, MockPolicyFrameworkConfig, MockPolicy } from "test/foundry/mocks/licensing/MockPolicyFrameworkManager.sol"; -import { MockAccessController } from "test/foundry/mocks/access/MockAccessController.sol"; -import { MockTokenGatedHook } from "test/foundry/mocks/MockTokenGatedHook.sol"; -import { MockERC721 } from "test/foundry/mocks/token/MockERC721.sol"; -import { BaseTest } from "test/foundry/utils/BaseTest.t.sol"; +import { MockPolicyFrameworkManager, MockPolicyFrameworkConfig, MockPolicy } from "../../mocks/licensing/MockPolicyFrameworkManager.sol"; +import { MockAccessController } from "../../mocks/access/MockAccessController.sol"; +import { MockTokenGatedHook } from "../../mocks/MockTokenGatedHook.sol"; +import { MockERC721 } from "../../mocks/token/MockERC721.sol"; +import { BaseTest } from "../../utils/BaseTest.t.sol"; contract LicensingModuleTest is BaseTest { using Strings for *; @@ -38,6 +40,8 @@ contract LicensingModuleTest is BaseTest { address public ipOwner = address(0x100); // use static address, otherwise uri check fails because licensor changes address public licenseHolder = address(0x101); + IRoyaltyPolicyLAP public mockRoyaltyPolicyLAP; + modifier withPolicyFrameworkManager() { licensingModule.registerPolicyFrameworkManager(address(mockPFM)); _; @@ -45,13 +49,6 @@ contract LicensingModuleTest is BaseTest { function setUp() public override { super.setUp(); - buildDeployModuleCondition( - DeployModuleCondition({ disputeModule: false, royaltyModule: false, licensingModule: true }) - ); - buildDeployPolicyCondition(DeployPolicyCondition({ arbitrationPolicySP: false, royaltyPolicyLAP: true })); - buildDeployRegistryCondition(DeployRegistryCondition({ licenseRegistry: true, moduleRegistry: false })); - deployConditionally(); - postDeploymentSetup(); // TODO: Mock this mockRoyaltyPolicyLAP = royaltyPolicyLAP; @@ -78,6 +75,8 @@ contract LicensingModuleTest is BaseTest { vm.label(ipId1, "IPAccount1"); vm.label(ipId2, "IPAccount2"); vm.label(ipId3, "IPAccount3"); + + useMock_RoyaltyPolicyLAP(); } function _createMockPolicy() internal pure returns (bytes memory) { diff --git a/test/foundry/modules/licensing/PILPolicyFramework.derivation.t.sol b/test/foundry/modules/licensing/PILPolicyFramework.derivation.t.sol index f2a330f6..35475c49 100644 --- a/test/foundry/modules/licensing/PILPolicyFramework.derivation.t.sol +++ b/test/foundry/modules/licensing/PILPolicyFramework.derivation.t.sol @@ -1,9 +1,6 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.23; -import { IAccessController } from "contracts/interfaces/access/IAccessController.sol"; -import { ILicensingModule } from "contracts/interfaces/modules/licensing/ILicensingModule.sol"; -import { IRoyaltyModule } from "contracts/interfaces/modules/royalty/IRoyaltyModule.sol"; import { Errors } from "contracts/lib/Errors.sol"; import { BaseTest } from "test/foundry/utils/BaseTest.t.sol"; @@ -30,20 +27,6 @@ contract PILPolicyFrameworkCompatibilityTest is BaseTest { function setUp() public override { super.setUp(); - buildDeployRegistryCondition(DeployRegistryCondition({ licenseRegistry: true, moduleRegistry: false })); - buildDeployModuleCondition( - DeployModuleCondition({ disputeModule: false, royaltyModule: false, licensingModule: true }) - ); - buildDeployPolicyCondition(DeployPolicyCondition({ royaltyPolicyLAP: true, arbitrationPolicySP: false })); - deployConditionally(); - postDeploymentSetup(); - - // Call `getXXX` here to either deploy mock or use real contracted deploy via the - // deployConditionally() call above. - // TODO: three options, auto/mock/real in deploy condition, so no need to call getXXX - accessController = IAccessController(getAccessController()); - licensingModule = ILicensingModule(getLicensingModule()); - royaltyModule = IRoyaltyModule(getRoyaltyModule()); _setPILPolicyFrameworkManager(); @@ -53,6 +36,8 @@ contract PILPolicyFrameworkCompatibilityTest is BaseTest { ipId2 = ipAccountRegistry.registerIpAccount(block.chainid, address(mockNFT), 2); vm.label(ipId1, "IP1"); vm.label(ipId2, "IP2"); + + useMock_RoyaltyPolicyLAP(); } ///////////////////////////////////////////////////////////// @@ -83,9 +68,11 @@ contract PILPolicyFrameworkCompatibilityTest is BaseTest { // Others can mint licenses to make derivatives of IP1 from each different policy, // as long as they pass the verifications + vm.startPrank(alice); uint256 licenseId1 = licensingModule.mintLicense(_getPilPolicyId("comm_deriv"), ipId1, 1, dan, ""); assertEq(licenseRegistry.balanceOf(dan, licenseId1), 1, "dan doesn't have license1"); + vm.startPrank(dan); uint256 licenseId2 = licensingModule.mintLicense(_getPilPolicyId("comm_non_deriv"), ipId1, 1, dan, ""); assertEq(licenseRegistry.balanceOf(dan, licenseId2), 1, "dan doesn't have license2"); } diff --git a/test/foundry/modules/licensing/PILPolicyFramework.multi-parent.sol b/test/foundry/modules/licensing/PILPolicyFramework.multi-parent.sol index 1bb2be6c..b17f8850 100644 --- a/test/foundry/modules/licensing/PILPolicyFramework.multi-parent.sol +++ b/test/foundry/modules/licensing/PILPolicyFramework.multi-parent.sol @@ -1,9 +1,6 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.23; -import { IAccessController } from "contracts/interfaces/access/IAccessController.sol"; -import { ILicensingModule } from "contracts/interfaces/modules/licensing/ILicensingModule.sol"; -import { IRoyaltyModule } from "contracts/interfaces/modules/royalty/IRoyaltyModule.sol"; import { Errors } from "contracts/lib/Errors.sol"; import { Licensing } from "contracts/lib/Licensing.sol"; import { PILFrameworkErrors } from "contracts/lib/PILFrameworkErrors.sol"; @@ -40,20 +37,6 @@ contract PILPolicyFrameworkMultiParentTest is BaseTest { function setUp() public override { super.setUp(); - buildDeployRegistryCondition(DeployRegistryCondition({ licenseRegistry: true, moduleRegistry: false })); - buildDeployModuleCondition( - DeployModuleCondition({ disputeModule: false, royaltyModule: false, licensingModule: true }) - ); - buildDeployPolicyCondition(DeployPolicyCondition({ royaltyPolicyLAP: true, arbitrationPolicySP: false })); - deployConditionally(); - postDeploymentSetup(); - - // Call `getXXX` here to either deploy mock or use real contracted deploy via the - // deployConditionally() call above. - // TODO: three options, auto/mock/real in deploy condition, so no need to call getXXX - accessController = IAccessController(getAccessController()); - licensingModule = ILicensingModule(getLicensingModule()); - royaltyModule = IRoyaltyModule(getRoyaltyModule()); _setPILPolicyFrameworkManager(); @@ -76,6 +59,8 @@ contract PILPolicyFrameworkMultiParentTest is BaseTest { vm.label(ipId2, "IP2"); vm.label(ipId3, "IP3"); vm.label(ipId4, "IP4"); + + useMock_RoyaltyPolicyLAP(); } function test_PILPolicyFramework_multiParent_AliceSets3Parents_SamePolicyReciprocal() @@ -404,11 +389,11 @@ contract PILPolicyFrameworkMultiParentTest is BaseTest { RegisterPILPolicyParams memory inputB ) internal returns (uint256 polAId, uint256 polBId) { polAId = _pilFramework().registerPolicy(inputA); - vm.prank(ipId1); + vm.prank(ipIdToOwner[ipId1]); licenses.push(licensingModule.mintLicense(polAId, ipId1, 1, alice, "")); polBId = _pilFramework().registerPolicy(inputB); - vm.prank(ipId2); + vm.prank(ipIdToOwner[ipId2]); licenses.push(licensingModule.mintLicense(polBId, ipId2, 2, alice, "")); } diff --git a/test/foundry/modules/licensing/PILPolicyFramework.t.sol b/test/foundry/modules/licensing/PILPolicyFramework.t.sol index ed08fb1b..66e1a7f7 100644 --- a/test/foundry/modules/licensing/PILPolicyFramework.t.sol +++ b/test/foundry/modules/licensing/PILPolicyFramework.t.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.23; -import { IAccessController } from "contracts/interfaces/access/IAccessController.sol"; -import { ILicensingModule } from "contracts/interfaces/modules/licensing/ILicensingModule.sol"; import { Errors } from "contracts/lib/Errors.sol"; import { PILFrameworkErrors } from "contracts/lib/PILFrameworkErrors.sol"; // solhint-disable-next-line max-line-length @@ -22,24 +20,6 @@ contract PILPolicyFrameworkTest is BaseTest { function setUp() public override { super.setUp(); - buildDeployRegistryCondition(DeployRegistryCondition({ licenseRegistry: true, moduleRegistry: false })); - buildDeployModuleCondition( - DeployModuleCondition({ disputeModule: false, royaltyModule: false, licensingModule: true }) - ); - buildDeployPolicyCondition( - DeployPolicyCondition({ - arbitrationPolicySP: false, - royaltyPolicyLAP: true // deploy to set address for commercial licenses - }) - ); - deployConditionally(); - postDeploymentSetup(); - - // Call `getXXX` here to either deploy mock or use real contracted deploy via the - // deployConditionally() call above. - // TODO: three options, auto/mock/real in deploy condition, so no need to call getXXX - accessController = IAccessController(getAccessController()); - licensingModule = ILicensingModule(getLicensingModule()); _setPILPolicyFrameworkManager(); diff --git a/test/foundry/modules/metadata/CoreMetadataModule.t.sol b/test/foundry/modules/metadata/CoreMetadataModule.t.sol index 7c968167..97bc4d9d 100644 --- a/test/foundry/modules/metadata/CoreMetadataModule.t.sol +++ b/test/foundry/modules/metadata/CoreMetadataModule.t.sol @@ -2,36 +2,24 @@ pragma solidity ^0.8.23; import { IIPAccount } from "../../../../contracts/interfaces/IIPAccount.sol"; -import { CoreMetadataModule } from "../../../../contracts/modules/metadata/CoreMetadataModule.sol"; import { ICoreMetadataModule } from "../../../../contracts/interfaces/modules/metadata/ICoreMetadataModule.sol"; import { Errors } from "../../../../contracts/lib/Errors.sol"; -import { CORE_METADATA_MODULE_KEY } from "../../../../contracts/lib/modules/Module.sol"; import { BaseTest } from "../../utils/BaseTest.t.sol"; import { IPAccountStorageOps } from "../../../../contracts/lib/IPAccountStorageOps.sol"; contract CoreMetadataModuleTest is BaseTest { using IPAccountStorageOps for IIPAccount; - CoreMetadataModule public coreMetadataModule; IIPAccount private ipAccount; function setUp() public override { super.setUp(); - buildDeployAccessCondition(DeployAccessCondition({ accessController: true, governance: true })); - buildDeployRegistryCondition(DeployRegistryCondition({ licenseRegistry: false, moduleRegistry: true })); - deployConditionally(); - postDeploymentSetup(); mockNFT.mintId(alice, 1); ipAccount = IIPAccount(payable(ipAssetRegistry.register(address(mockNFT), 1))); vm.label(address(ipAccount), "IPAccount1"); - - coreMetadataModule = new CoreMetadataModule(address(accessController), address(ipAssetRegistry)); - - vm.prank(u.admin); - moduleRegistry.registerModule(CORE_METADATA_MODULE_KEY, address(coreMetadataModule)); } function test_CoreMetadata_NftTokenURI() public { diff --git a/test/foundry/modules/metadata/CoreMetadataViewModule.t.sol b/test/foundry/modules/metadata/CoreMetadataViewModule.t.sol index f06bba73..ddf42169 100644 --- a/test/foundry/modules/metadata/CoreMetadataViewModule.t.sol +++ b/test/foundry/modules/metadata/CoreMetadataViewModule.t.sol @@ -4,10 +4,7 @@ pragma solidity ^0.8.23; import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; import { Base64 } from "@openzeppelin/contracts/utils/Base64.sol"; import { IIPAccount } from "../../../../contracts/interfaces/IIPAccount.sol"; -import { CoreMetadataModule } from "../../../../contracts/modules/metadata/CoreMetadataModule.sol"; import { CoreMetadataViewModule } from "../../../../contracts/modules/metadata/CoreMetadataViewModule.sol"; -import { CORE_METADATA_MODULE_KEY } from "../../../../contracts/lib/modules/Module.sol"; -import { CORE_METADATA_VIEW_MODULE_KEY } from "../../../../contracts/lib/modules/Module.sol"; import { BaseTest } from "../../utils/BaseTest.t.sol"; import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; import { IPAccountStorageOps } from "../../../../contracts/lib/IPAccountStorageOps.sol"; @@ -16,32 +13,16 @@ contract CoreMetadataViewModuleTest is BaseTest { using IPAccountStorageOps for IIPAccount; using Strings for *; - CoreMetadataModule public coreMetadataModule; - CoreMetadataViewModule public coreMetadataViewModule; IIPAccount private ipAccount; function setUp() public override { super.setUp(); - buildDeployAccessCondition(DeployAccessCondition({ accessController: true, governance: true })); - buildDeployRegistryCondition(DeployRegistryCondition({ licenseRegistry: false, moduleRegistry: true })); - deployConditionally(); - postDeploymentSetup(); mockNFT.mintId(alice, 99); ipAccount = IIPAccount(payable(ipAssetRegistry.register(address(mockNFT), 99))); vm.label(address(ipAccount), "IPAccount1"); - - coreMetadataModule = new CoreMetadataModule(address(accessController), address(ipAssetRegistry)); - coreMetadataViewModule = new CoreMetadataViewModule(address(ipAssetRegistry), address(moduleRegistry)); - - vm.startPrank(u.admin); - moduleRegistry.registerModule(CORE_METADATA_MODULE_KEY, address(coreMetadataModule)); - moduleRegistry.registerModule(CORE_METADATA_VIEW_MODULE_KEY, address(coreMetadataViewModule)); - vm.stopPrank(); - - coreMetadataViewModule.updateCoreMetadataModule(); } function test_CoreMetadataViewModule_GetAllMetadata() public { diff --git a/test/foundry/modules/metadata/MetadataModule.t.sol b/test/foundry/modules/metadata/MetadataModule.t.sol index a0f6a410..f79a60d0 100644 --- a/test/foundry/modules/metadata/MetadataModule.t.sol +++ b/test/foundry/modules/metadata/MetadataModule.t.sol @@ -9,19 +9,25 @@ import { BaseTest } from "../../utils/BaseTest.t.sol"; contract MetadataModuleTest is BaseTest { MockModule public module; - MockCoreMetadataViewModule public coreMetadataViewModule; MockAllMetadataViewModule public allMetadataViewModule; MockMetadataModule public metadataModule; function setUp() public override { super.setUp(); - deployConditionally(); - postDeploymentSetup(); metadataModule = new MockMetadataModule(address(accessController), address(ipAssetRegistry)); module = new MockModule(address(ipAssetRegistry), address(moduleRegistry), "MockModule"); - coreMetadataViewModule = new MockCoreMetadataViewModule(address(ipAssetRegistry)); + + vm.etch( + address(coreMetadataViewModule), + address(new MockCoreMetadataViewModule(address(ipAssetRegistry))).code + ); allMetadataViewModule = new MockAllMetadataViewModule(address(ipAssetRegistry), address(metadataModule)); + + vm.startPrank(u.admin); + moduleRegistry.registerModule("MockModule", address(module)); + moduleRegistry.registerModule("MockMetadataModule", address(metadataModule)); + vm.stopPrank(); } function test_Metadata_OptionalMetadata() public { diff --git a/test/foundry/modules/royalty/IpRoyaltyVault.t.sol b/test/foundry/modules/royalty/IpRoyaltyVault.t.sol index 8aa39290..ed0e9952 100644 --- a/test/foundry/modules/royalty/IpRoyaltyVault.t.sol +++ b/test/foundry/modules/royalty/IpRoyaltyVault.t.sol @@ -11,16 +11,10 @@ import { Errors } from "../../../../contracts/lib/Errors.sol"; import { BaseTest } from "../../utils/BaseTest.t.sol"; contract TestIpRoyaltyVault is BaseTest { - IpRoyaltyVault ipRoyaltyVault; + IpRoyaltyVault private ipRoyaltyVault; function setUp() public override { super.setUp(); - buildDeployModuleCondition( - DeployModuleCondition({ disputeModule: false, royaltyModule: true, licensingModule: false }) - ); - buildDeployPolicyCondition(DeployPolicyCondition({ arbitrationPolicySP: false, royaltyPolicyLAP: true })); - deployConditionally(); - postDeploymentSetup(); vm.startPrank(u.admin); // whitelist royalty policy diff --git a/test/foundry/modules/royalty/RoyaltyModule.t.sol b/test/foundry/modules/royalty/RoyaltyModule.t.sol index 464ba966..fdf0778e 100644 --- a/test/foundry/modules/royalty/RoyaltyModule.t.sol +++ b/test/foundry/modules/royalty/RoyaltyModule.t.sol @@ -44,18 +44,12 @@ contract TestRoyaltyModule is BaseTest { function setUp() public override { super.setUp(); - buildDeployModuleCondition( - DeployModuleCondition({ disputeModule: true, royaltyModule: true, licensingModule: false }) - ); - buildDeployPolicyCondition(DeployPolicyCondition({ arbitrationPolicySP: true, royaltyPolicyLAP: true })); - deployConditionally(); - postDeploymentSetup(); USDC.mint(ipAccount2, 1000 * 10 ** 6); // 1000 USDC - address impl = address(new RoyaltyPolicyLAP(getRoyaltyModule(), getLicensingModule())); + address impl = address(new RoyaltyPolicyLAP(address(royaltyModule), address(licensingModule))); royaltyPolicyLAP2 = RoyaltyPolicyLAP( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(RoyaltyPolicyLAP.initialize, (getGovernance()))) + TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(RoyaltyPolicyLAP.initialize, address(governance))) ); arbitrationRelayer = u.admin; @@ -175,7 +169,7 @@ contract TestRoyaltyModule is BaseTest { function test_RoyaltyModule_setDisputeModule_revert_ZeroDisputeModule() public { address impl = address(new RoyaltyModule()); RoyaltyModule testRoyaltyModule = RoyaltyModule( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(RoyaltyModule.initialize, (address(getGovernance())))) + TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(RoyaltyModule.initialize, address(governance))) ); vm.expectRevert(Errors.RoyaltyModule__ZeroDisputeModule.selector); vm.prank(u.admin); @@ -186,7 +180,7 @@ contract TestRoyaltyModule is BaseTest { vm.startPrank(u.admin); address impl = address(new RoyaltyModule()); RoyaltyModule testRoyaltyModule = RoyaltyModule( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(RoyaltyModule.initialize, (address(getGovernance())))) + TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(RoyaltyModule.initialize, address(governance))) ); testRoyaltyModule.setDisputeModule(address(disputeModule)); assertEq(testRoyaltyModule.disputeModule(), address(disputeModule)); @@ -202,7 +196,7 @@ contract TestRoyaltyModule is BaseTest { vm.startPrank(u.admin); address impl = address(new RoyaltyModule()); RoyaltyModule testRoyaltyModule = RoyaltyModule( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(RoyaltyModule.initialize, (address(getGovernance())))) + TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(RoyaltyModule.initialize, address(governance))) ); testRoyaltyModule.setLicensingModule(address(licensingModule)); assertEq(testRoyaltyModule.licensingModule(), address(licensingModule)); diff --git a/test/foundry/modules/royalty/RoyaltyPolicyLAP.t.sol b/test/foundry/modules/royalty/RoyaltyPolicyLAP.t.sol index 41a5cda6..4085e93a 100644 --- a/test/foundry/modules/royalty/RoyaltyPolicyLAP.t.sol +++ b/test/foundry/modules/royalty/RoyaltyPolicyLAP.t.sol @@ -15,12 +15,6 @@ contract TestRoyaltyPolicyLAP is BaseTest { function setUp() public override { super.setUp(); - buildDeployModuleCondition( - DeployModuleCondition({ disputeModule: false, royaltyModule: true, licensingModule: false }) - ); - buildDeployPolicyCondition(DeployPolicyCondition({ arbitrationPolicySP: false, royaltyPolicyLAP: true })); - deployConditionally(); - postDeploymentSetup(); vm.startPrank(u.admin); // whitelist royalty policy diff --git a/test/foundry/registries/IPAccountRegistry.t.sol b/test/foundry/registries/IPAccountRegistry.t.sol index 6579b147..471175f1 100644 --- a/test/foundry/registries/IPAccountRegistry.t.sol +++ b/test/foundry/registries/IPAccountRegistry.t.sol @@ -16,8 +16,6 @@ contract IPAccountRegistryTest is BaseTest { function setUp() public override { super.setUp(); - deployConditionally(); - postDeploymentSetup(); } function test_IPAccountRegistry_registerIpAccount() public { diff --git a/test/foundry/registries/IPAssetRegistry.t.sol b/test/foundry/registries/IPAssetRegistry.t.sol index 0cf01ee2..13acf12c 100644 --- a/test/foundry/registries/IPAssetRegistry.t.sol +++ b/test/foundry/registries/IPAssetRegistry.t.sol @@ -35,14 +35,6 @@ contract IPAssetRegistryTest is BaseTest { /// @notice Initializes the IP asset registry testing contract. function setUp() public virtual override { super.setUp(); - buildDeployRegistryCondition( - DeployRegistryCondition({ - licenseRegistry: false, // don't use - moduleRegistry: false // use mock - }) - ); - deployConditionally(); - postDeploymentSetup(); registry = ipAssetRegistry; diff --git a/test/foundry/registries/ModuleRegistry.t.sol b/test/foundry/registries/ModuleRegistry.t.sol index 74723635..c8b6ef8b 100644 --- a/test/foundry/registries/ModuleRegistry.t.sol +++ b/test/foundry/registries/ModuleRegistry.t.sol @@ -19,9 +19,6 @@ contract ModuleRegistryTest is BaseTest { function setUp() public override { super.setUp(); - buildDeployRegistryCondition(DeployRegistryCondition({ licenseRegistry: false, moduleRegistry: true })); - deployConditionally(); - postDeploymentSetup(); module = new MockModule(address(ipAccountRegistry), address(moduleRegistry), "MockModule"); customModule = new CustomModule(); diff --git a/test/foundry/utils/BaseTest.t.sol b/test/foundry/utils/BaseTest.t.sol index a7ffeea7..367f0f94 100644 --- a/test/foundry/utils/BaseTest.t.sol +++ b/test/foundry/utils/BaseTest.t.sol @@ -3,22 +3,15 @@ pragma solidity 0.8.23; // external -import { console2 } from "forge-std/console2.sol"; // console to indicate mock deployment calls. import { Test } from "forge-std/Test.sol"; - -// contracts -import { AccessController } from "../../../contracts/access/AccessController.sol"; -// solhint-disable-next-line max-line-length -import { DISPUTE_MODULE_KEY, ROYALTY_MODULE_KEY, LICENSING_MODULE_KEY } from "../../../contracts/lib/modules/Module.sol"; -import { AccessPermission } from "../../../contracts/lib/AccessPermission.sol"; -import { LicenseRegistry } from "../../../contracts/registries/LicenseRegistry.sol"; -import { RoyaltyModule } from "../../../contracts/modules/royalty/RoyaltyModule.sol"; +import { ERC6551Registry } from "erc6551/ERC6551Registry.sol"; // test -import { DeployHelper } from "./DeployHelper.t.sol"; +import { DeployHelper } from "../../../script/foundry/utils/DeployHelper.sol"; import { LicensingHelper } from "./LicensingHelper.t.sol"; import { MockERC20 } from "../mocks/token/MockERC20.sol"; import { MockERC721 } from "../mocks/token/MockERC721.sol"; +import { MockRoyaltyPolicyLAP } from "../mocks/policy/MockRoyaltyPolicyLAP.sol"; import { Users, UsersLib } from "./Users.t.sol"; /// @title Base Test Contract @@ -35,44 +28,46 @@ contract BaseTest is Test, DeployHelper, LicensingHelper { address internal carl; address internal dan; + ERC6551Registry internal ERC6551_REGISTRY = new ERC6551Registry(); + + MockERC20 internal erc20 = new MockERC20(); + MockERC20 internal erc20bb = new MockERC20(); + /// @dev Aliases for mock assets. - /// NOTE: Must call `postDeploymentSetup` after `deployConditionally` to set these. MockERC20 internal mockToken; // alias for erc20 MockERC20 internal USDC; // alias for mockToken/erc20 MockERC20 internal LINK; // alias for erc20bb - MockERC721 internal mockNFT; // alias for erc721.ape + MockERC721 internal mockNFT; + + uint256 internal constant ARBITRATION_PRICE = 1000 * 10 ** 6; // 1000 MockToken (6 decimals) + uint256 internal constant MAX_ROYALTY_APPROVAL = 10000 ether; + + constructor() DeployHelper(address(ERC6551_REGISTRY), address(erc20), ARBITRATION_PRICE, MAX_ROYALTY_APPROVAL) {} /// @notice Sets up the base test contract. function setUp() public virtual { u = UsersLib.createMockUsers(vm); - setGovernanceAdmin(u.admin); admin = u.admin; alice = u.alice; bob = u.bob; carl = u.carl; dan = u.dan; - } - function postDeploymentSetup() public { - if (postDeployConditions.accessController_init) initAccessController(); - if (postDeployConditions.moduleRegistry_registerModules) registerModules(); - if (postDeployConditions.royaltyModule_configure) configureRoyaltyModule(); - if (postDeployConditions.disputeModule_configure) configureDisputeModule(); - if (deployConditions.registry.licenseRegistry) configureLicenseRegistry(); - if (deployConditions.policy.royaltyPolicyLAP) configureRoyaltyPolicyLAP(); - - bool isMockRoyaltyPolicyLAP = address(royaltyPolicyLAP) == address(0) && - address(mockRoyaltyPolicyLAP) != address(0); + // deploy all contracts via DeployHelper + super.run( + address(u.admin), + false, // configByMultisig + false, // runStorageLayoutCheck + false // writeDeploys + ); - // Initialize licensing helper - // TODO: conditionally init and use LicensingHelper. initLicensingHelper( - getAccessController(), + address(accessController), address(ipAccountRegistry), - getLicensingModule(), - getRoyaltyModule(), - isMockRoyaltyPolicyLAP ? address(mockRoyaltyPolicyLAP) : address(royaltyPolicyLAP), + address(licensingModule), + address(royaltyModule), + address(royaltyPolicyLAP), address(erc20) ); @@ -80,7 +75,9 @@ contract BaseTest is Test, DeployHelper, LicensingHelper { mockToken = erc20; USDC = erc20; LINK = erc20bb; - mockNFT = erc721.ape; + mockNFT = new MockERC721("Ape"); + + dealMockAssets(); } function dealMockAssets() public { @@ -95,113 +92,8 @@ contract BaseTest is Test, DeployHelper, LicensingHelper { erc20bb.mint(u.dan, 1000 * 10 ** erc20bb.decimals()); } - /// @dev Initialize the access controller to abstract away access controller initialization when testing - function initAccessController() public { - console2.log("BaseTest PostDeploymentSetup: Init Access Controller"); - require(address(ipAccountRegistry) != address(0), "ipAccountRegistry not set"); - vm.startPrank(u.admin); - - // NOTE: accessController is IAccessController, which doesn't expose `initialize` function. - AccessController(address(accessController)).setAddresses(address(ipAccountRegistry), getModuleRegistry()); - - accessController.setGlobalPermission( - address(ipAssetRegistry), - address(licensingModule), - bytes4(licensingModule.linkIpToParents.selector), - AccessPermission.ALLOW - ); - - // If REAL IPAssetRegistry and LicensingModule are deployed, set global permissions - // (NOTE: for now, IPAssetRegistry is always deployed with real contract) - if (deployConditions.module.licensingModule) { - accessController.setGlobalPermission( - address(ipAssetRegistry), - address(licensingModule), - bytes4(licensingModule.linkIpToParents.selector), - AccessPermission.ALLOW - ); - - accessController.setGlobalPermission( - address(ipAssetRegistry), - address(licensingModule), - bytes4(licensingModule.addPolicyToIp.selector), - AccessPermission.ALLOW - ); - } - - vm.stopPrank(); - } - - /// @dev Register modules to abstract away module registration when testing - function registerModules() public { - console2.log("BaseTest PostDeploymentSetup: Register Modules"); - vm.startPrank(u.admin); - // TODO: option to register "hookmodule", which will trigger the call below: - // moduleRegistry.registerModuleType(MODULE_TYPE_HOOK, type(IHookModule).interfaceId); - - if (address(disputeModule) != address(0)) { - moduleRegistry.registerModule(DISPUTE_MODULE_KEY, address(disputeModule)); - } - if (address(licensingModule) != address(0)) { - moduleRegistry.registerModule(LICENSING_MODULE_KEY, address(licensingModule)); - } - if (address(royaltyModule) != address(0)) { - moduleRegistry.registerModule(ROYALTY_MODULE_KEY, address(royaltyModule)); - } - vm.stopPrank(); - } - - /// @dev Pre-set configs to abstract away configs when testing with royalty module - function configureRoyaltyModule() public { - console2.log("BaseTest PostDeploymentSetup: Configure Royalty Module"); - require(address(royaltyModule) != address(0), "royaltyModule not set"); - - vm.startPrank(u.admin); - RoyaltyModule(address(royaltyModule)).setLicensingModule(getLicensingModule()); - RoyaltyModule(address(royaltyModule)).setDisputeModule(getDisputeModule()); - royaltyModule.whitelistRoyaltyToken(address(erc20), true); - if (address(royaltyPolicyLAP) != address(0)) { - royaltyModule.whitelistRoyaltyPolicy(address(royaltyPolicyLAP), true); - } - vm.stopPrank(); - } - - /// @dev Pre-set configs to abstract away configs when testing with dispute module - function configureDisputeModule() public { - console2.log("BaseTest PostDeploymentSetup: Configure Dispute Module"); - require(address(disputeModule) != address(0), "disputeModule not set"); - - vm.startPrank(u.admin); - disputeModule.whitelistDisputeTag("PLAGIARISM", true); - if (address(arbitrationPolicySP) != address(0)) { - disputeModule.whitelistArbitrationPolicy(address(arbitrationPolicySP), true); - disputeModule.whitelistArbitrationRelayer(address(arbitrationPolicySP), u.admin, true); - disputeModule.setBaseArbitrationPolicy(address(arbitrationPolicySP)); - } - vm.stopPrank(); - } - - function configureLicenseRegistry() public { - console2.log("BaseTest PostDeploymentSetup: Configure License Registry"); - require(address(licenseRegistry) != address(0), "licenseRegistry not set"); - - vm.startPrank(u.admin); - // Need to cast to LicenseRegistry to set dispute and licensing module, as interface doesn't expose those fns. - LicenseRegistry(address(licenseRegistry)).setDisputeModule(getDisputeModule()); - LicenseRegistry(address(licenseRegistry)).setLicensingModule(getLicensingModule()); - vm.stopPrank(); - } - - function configureRoyaltyPolicyLAP() public { - console2.log("BaseTest PostDeploymentSetup: Configure Royalty Policy LAP"); - require(address(royaltyPolicyLAP) != address(0), "royaltyPolicyLAP not set"); - } - - function _getIpId(MockERC721 mnft, uint256 tokenId) internal view returns (address ipId) { - return _getIpId(address(mnft), tokenId); - } - - function _getIpId(address mnft, uint256 tokenId) internal view returns (address ipId) { - return ipAccountRegistry.ipAccount(block.chainid, mnft, tokenId); + function useMock_RoyaltyPolicyLAP() internal { + address impl = address(new MockRoyaltyPolicyLAP()); + vm.etch(address(royaltyPolicyLAP), impl.code); } } diff --git a/test/foundry/utils/DeployHelper.t.sol b/test/foundry/utils/DeployHelper.t.sol deleted file mode 100644 index 1006a2bf..00000000 --- a/test/foundry/utils/DeployHelper.t.sol +++ /dev/null @@ -1,396 +0,0 @@ -/* solhint-disable no-console */ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.23; - -// external -import { console2 } from "forge-std/console2.sol"; // console to indicate mock deployment calls. -import { Test } from "forge-std/Test.sol"; -import { ERC6551Registry } from "erc6551/ERC6551Registry.sol"; -import { UpgradeableBeacon } from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; - -// contracts -import { AccessController } from "../../../contracts/access/AccessController.sol"; -import { Governance } from "../../../contracts/governance/Governance.sol"; -import { IAccessController } from "../../../contracts/interfaces/access/IAccessController.sol"; -import { IGovernance } from "../../../contracts/interfaces/governance/IGovernance.sol"; -import { IDisputeModule } from "../../../contracts/interfaces/modules/dispute/IDisputeModule.sol"; -import { ILicensingModule } from "../../../contracts/interfaces/modules/licensing/ILicensingModule.sol"; -import { IRoyaltyModule } from "../../../contracts/interfaces/modules/royalty/IRoyaltyModule.sol"; -import { ILicenseRegistry } from "../../../contracts/interfaces/registries/ILicenseRegistry.sol"; -import { IModuleRegistry } from "../../../contracts/interfaces/registries/IModuleRegistry.sol"; -import { IPAccountImpl } from "../../../contracts/IPAccountImpl.sol"; -import { IPAccountRegistry } from "../../../contracts/registries/IPAccountRegistry.sol"; -import { IPAssetRegistry } from "../../../contracts/registries/IPAssetRegistry.sol"; -import { ModuleRegistry } from "../../../contracts/registries/ModuleRegistry.sol"; -import { LicenseRegistry } from "../../../contracts/registries/LicenseRegistry.sol"; -import { RoyaltyModule } from "../../../contracts/modules/royalty/RoyaltyModule.sol"; -import { RoyaltyPolicyLAP } from "../../../contracts/modules/royalty/policies/RoyaltyPolicyLAP.sol"; -import { DisputeModule } from "../../../contracts/modules/dispute/DisputeModule.sol"; -import { LicensingModule } from "../../../contracts/modules/licensing/LicensingModule.sol"; -import { ArbitrationPolicySP } from "../../../contracts/modules/dispute/policies/ArbitrationPolicySP.sol"; -import { IpRoyaltyVault } from "../../../contracts/modules/royalty/policies/IpRoyaltyVault.sol"; - -// test -import { MockAccessController } from "../mocks/access/MockAccessController.sol"; -import { MockGovernance } from "../mocks/governance/MockGovernance.sol"; -import { MockDisputeModule } from "../mocks/module/MockDisputeModule.sol"; -import { MockLicensingModule } from "../mocks/module/MockLicensingModule.sol"; -import { MockRoyaltyModule } from "../mocks/module/MockRoyaltyModule.sol"; -import { MockArbitrationPolicy } from "../mocks/policy/MockArbitrationPolicy.sol"; -import { MockLicenseRegistry } from "../mocks/registry/MockLicenseRegistry.sol"; -import { MockModuleRegistry } from "../mocks/registry/MockModuleRegistry.sol"; -import { MockERC20 } from "../mocks/token/MockERC20.sol"; -import { MockERC721 } from "../mocks/token/MockERC721.sol"; -import { TestProxyHelper } from "./TestProxyHelper.sol"; - -contract DeployHelper is Test { - // TODO: three options, auto/mock/real in deploy condition, so that we don't need to manually - // call getXXX to get mock contract (if there's no real contract deployed). - - struct DeployRegistryCondition { - // bool ipAccountRegistry; // TODO: Add option for mock IPAccountRegistry - // bool ipAssetRegistry; // TODO: Add option for mock IPAssetRegistry - bool licenseRegistry; - bool moduleRegistry; - } - - struct DeployModuleCondition { - bool disputeModule; - bool royaltyModule; - bool licensingModule; - } - - struct DeployAccessCondition { - bool accessController; - bool governance; - } - - struct DeployPolicyCondition { - bool arbitrationPolicySP; - bool royaltyPolicyLAP; - } - - /// @dev Conditions that determine whether to deploy a contract. - struct DeployConditions { - DeployRegistryCondition registry; - DeployModuleCondition module; - DeployAccessCondition access; - DeployPolicyCondition policy; - } - - /// @dev Store deployment info for post-deployment setups. - struct PostDeployConditions { - bool accessController_init; - bool moduleRegistry_registerModules; - bool royaltyModule_configure; - bool disputeModule_configure; - } - - struct MockERC721s { - MockERC721 ape; - MockERC721 cat; - MockERC721 dog; - } - - // IPAccount - ERC6551Registry internal erc6551Registry; - IPAccountImpl internal ipAccountImpl; - - // Registry - IModuleRegistry internal moduleRegistry; - IPAccountRegistry internal ipAccountRegistry; - IPAssetRegistry internal ipAssetRegistry; - ILicenseRegistry internal licenseRegistry; - - // Module - IDisputeModule internal disputeModule; - IRoyaltyModule internal royaltyModule; - ILicensingModule internal licensingModule; - - // Access - IGovernance internal governance; - IAccessController internal accessController; - - // Policy - ArbitrationPolicySP internal arbitrationPolicySP; - RoyaltyPolicyLAP internal royaltyPolicyLAP; - - // Arbitration Policy - // TODO: custom arbitration price for testing - uint256 internal constant ARBITRATION_PRICE = 1000; // not decimal exponentiated - - // Mock - MockERC20 internal erc20; - MockERC20 internal erc20bb; - MockERC721s internal erc721; - MockArbitrationPolicy internal mockArbitrationPolicy; - // TODO: create mock - RoyaltyPolicyLAP internal mockRoyaltyPolicyLAP; - - // DeployHelper - DeployConditions internal deployConditions; - PostDeployConditions internal postDeployConditions; - address private governanceAdmin; - - function setGovernanceAdmin(address admin) public { - governanceAdmin = admin; - } - - function buildDeployRegistryCondition(DeployRegistryCondition memory d) public { - deployConditions.registry = d; - } - - function buildDeployModuleCondition(DeployModuleCondition memory d) public { - deployConditions.module = d; - } - - function buildDeployAccessCondition(DeployAccessCondition memory d) public { - deployConditions.access = d; - } - - function buildDeployPolicyCondition(DeployPolicyCondition memory d) public { - deployConditions.policy = d; - } - - /// @notice Deploys all contracts for integration test. - function deployIntegration() public { - buildDeployRegistryCondition(DeployRegistryCondition(true, true)); - buildDeployModuleCondition(DeployModuleCondition(true, true, true)); - buildDeployAccessCondition(DeployAccessCondition(true, true)); - buildDeployPolicyCondition(DeployPolicyCondition(true, true)); - - deployConditionally(); - } - - /// @notice Deploys contracts conditionally based on DeployConditions state variable. - function deployConditionally() public { - require(governanceAdmin != address(0), "DeployHelper: Governance admin not set, setGovernanceAdmin(address)"); - - DeployConditions memory dc = deployConditions; // alias - - erc6551Registry = new ERC6551Registry(); - - _deployMockAssets(); - - _deployAccessConditionally(dc.access); - - ipAccountImpl = new IPAccountImpl(address(accessController)); - - _deployRegistryConditionally(dc.registry); - _deployModuleConditionally(dc.module); - _deployPolicyConditionally(dc.policy); - } - - function _deployMockAssets() public { - erc20 = new MockERC20(); - erc20bb = new MockERC20(); - erc721 = MockERC721s({ ape: new MockERC721("Ape"), cat: new MockERC721("Cat"), dog: new MockERC721("Dog") }); - } - - function _deployAccessConditionally(DeployAccessCondition memory d) public { - if (d.governance) { - governance = new Governance(governanceAdmin); - console2.log("DeployHelper: Using REAL Governance"); - } - if (d.accessController) { - address impl = address(new AccessController()); - accessController = AccessController( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(AccessController.initialize, (getGovernance()))) - ); - - console2.log("DeployHelper: Using REAL AccessController"); - postDeployConditions.accessController_init = true; - // Access Controller uses IPAccountRegistry in its initialize function. - // TODO: Use mock IPAccountRegistry, instead of forcing deployment of actual IPAccountRegistry - // contract when using AccessController. - // deployConditions.registry.ipAccountRegistry = true; - } else { - accessController = new MockAccessController(); - console2.log("DeployHelper: Using Mock AccessController"); - } - } - - function _deployRegistryConditionally(DeployRegistryCondition memory d) public { - if (d.moduleRegistry) { - address impl = address(new ModuleRegistry()); - moduleRegistry = ModuleRegistry( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(AccessController.initialize, (getGovernance()))) - ); - console2.log("DeployHelper: Using REAL ModuleRegistry"); - postDeployConditions.moduleRegistry_registerModules = true; - } - - // TODO: Allow using mock IPAccountRegistry, instead of forcing deployment of actual IPAccountRegistry. - ipAccountRegistry = new IPAccountRegistry(address(erc6551Registry), address(ipAccountImpl)); - console2.log("DeployHelper: Using REAL IPAccountRegistry"); - - // TODO: Allow using mock IPAssetRegistry, instead of forcing deployment of actual IPAssetRegistry. - ipAssetRegistry = new IPAssetRegistry(address(erc6551Registry), address(ipAccountImpl), getGovernance()); - console2.log("DeployHelper: Using REAL IPAssetRegistry"); - - if (d.licenseRegistry) { - address newIml = address(new LicenseRegistry()); - licenseRegistry = LicenseRegistry( - TestProxyHelper.deployUUPSProxy( - newIml, - abi.encodeCall(LicenseRegistry.initialize, (address(getGovernance()), "deploy helper")) - ) - ); - console2.log("DeployHelper: Using REAL LicenseRegistry"); - } - } - - function _deployModuleConditionally(DeployModuleCondition memory d) public { - if (d.royaltyModule) { - address impl = address(new RoyaltyModule()); - royaltyModule = RoyaltyModule( - TestProxyHelper.deployUUPSProxy( - impl, - abi.encodeCall(RoyaltyModule.initialize, (address(getGovernance()))) - ) - ); - console2.log("DeployHelper: Using REAL RoyaltyModule"); - postDeployConditions.royaltyModule_configure = true; - } - if (d.disputeModule) { - require(address(ipAssetRegistry) != address(0), "DeployHelper Module: IPAssetRegistry required"); - address impl = address(new DisputeModule(address(accessController), address(ipAssetRegistry))); - disputeModule = DisputeModule( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(DisputeModule.initialize, (address(governance)))) - ); - console2.log("DeployHelper: Using REAL DisputeModule"); - postDeployConditions.disputeModule_configure = true; - } - if (d.licensingModule) { - require(address(ipAccountRegistry) != address(0), "DeployHelper Module: IPAccountRegistry required"); - address impl = address( - new LicensingModule( - getAccessController(), - address(ipAccountRegistry), - getRoyaltyModule(), - getLicenseRegistry(), - getDisputeModule() - ) - ); - licensingModule = LicensingModule( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(LicensingModule.initialize, (getGovernance()))) - ); - console2.log("DeployHelper: Using REAL LicensingModule"); - } - } - - function _deployPolicyConditionally(DeployPolicyCondition memory d) public { - if (d.arbitrationPolicySP) { - address impl = address(new ArbitrationPolicySP(getDisputeModule(), address(erc20), ARBITRATION_PRICE)); - arbitrationPolicySP = ArbitrationPolicySP( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(ArbitrationPolicySP.initialize, (getGovernance()))) - ); - console2.log("DeployHelper: Using REAL ArbitrationPolicySP"); - } else { - mockArbitrationPolicy = new MockArbitrationPolicy(getDisputeModule(), address(erc20), ARBITRATION_PRICE); - console2.log("DeployHelper: Using Mock ArbitrationPolicySP"); - } - if (d.royaltyPolicyLAP) { - address impl = address(new RoyaltyPolicyLAP(getRoyaltyModule(), getLicensingModule())); - royaltyPolicyLAP = RoyaltyPolicyLAP( - TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(RoyaltyPolicyLAP.initialize, (getGovernance()))) - ); - console2.log("DeployHelper: Using REAL RoyaltyPolicyLAP"); - - // deploy ip royalty vault implementation and beacon - vm.startPrank(governanceAdmin); - address ipRoyaltyVaultImplementation = address( - new IpRoyaltyVault(address(royaltyPolicyLAP), address(disputeModule)) - ); - address ipRoyaltyVaultBeacon = address( - new UpgradeableBeacon(ipRoyaltyVaultImplementation, getGovernance()) - ); - royaltyPolicyLAP.setIpRoyaltyVaultBeacon(ipRoyaltyVaultBeacon); - } else { - // mockRoyaltyPolicyLAP = new MockRoyaltyPolicyLAP(getRoyaltyModule()); - // console2.log("DeployHelper: Using Mock RoyaltyPolicyLAP"); - } - } - - /// @dev Get or deploy mock Access Controller. - function getAccessController() public returns (address) { - if (address(accessController) == address(0)) { - accessController = new MockAccessController(); - // solhint-disable-next-line no-console - console2.log("DeployHelper: Using Mock AccessController"); - } - if (!postDeployConditions.accessController_init) { - postDeployConditions.accessController_init = true; - } - return address(accessController); - } - - /// @dev Get or deploy mock Dispute Module. - function getDisputeModule() public returns (address) { - if (address(disputeModule) == address(0)) { - disputeModule = new MockDisputeModule(); - // solhint-disable-next-line no-console - console2.log("DeployHelper: Using Mock DisputeModule"); - } - if (!postDeployConditions.disputeModule_configure) { - postDeployConditions.disputeModule_configure = true; - } - return address(disputeModule); - } - - /// @dev Get or deploy mock Governance. - function getGovernance() public returns (address) { - if (address(governance) == address(0)) { - governance = new MockGovernance(governanceAdmin); - // solhint-disable-next-line no-console - console2.log("DeployHelper: Using Mock Governance"); - } - return address(governance); - } - - /// @dev Get or deploy mock Licensing Module. - function getLicensingModule() public returns (address) { - if (address(licensingModule) == address(0)) { - licensingModule = new MockLicensingModule(getRoyaltyModule(), getLicenseRegistry()); - // solhint-disable-next-line no-console - console2.log("DeployHelper: Using Mock LicensingModule"); - } - return address(licensingModule); - } - - /// @dev Get or deploy mock License Registry. - function getLicenseRegistry() public returns (address) { - if (address(licenseRegistry) == address(0)) { - licenseRegistry = new MockLicenseRegistry(); - // solhint-disable-next-line no-console - console2.log("DeployHelper: Using Mock LicenseRegistry"); - } - return address(licenseRegistry); - } - - /// @dev Get or deploy mock Module Registry. - function getModuleRegistry() public returns (address) { - if (address(moduleRegistry) == address(0)) { - moduleRegistry = new MockModuleRegistry(); - // solhint-disable-next-line no-console - console2.log("DeployHelper: Using Mock ModuleRegistry"); - } - if (!postDeployConditions.moduleRegistry_registerModules) { - postDeployConditions.moduleRegistry_registerModules = true; - } - return address(moduleRegistry); - } - - /// @dev Get or deploy mock Royalty Module. - function getRoyaltyModule() public returns (address) { - if (address(royaltyModule) == address(0)) { - royaltyModule = new MockRoyaltyModule(); - // solhint-disable-next-line no-console - console2.log("DeployHelper: Using Mock RoyaltyModule"); - } - if (!postDeployConditions.royaltyModule_configure) { - postDeployConditions.royaltyModule_configure = true; - } - return address(royaltyModule); - } -}