Skip to content

Commit

Permalink
Merge branch 'dev' into authorization-refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
leeren authored Dec 8, 2023
2 parents dd696a9 + 2ad8bad commit df2c14f
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 73 deletions.
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ SEPOLIA_ADMIN_ADDRESS = 0x12341234123412341234123412341234
ETHERSCAN_API_KEY = ETHERSCANAPIKEYETHERSCANAPIKEY

# PROTOCOL LICENSE URL
PIPL_URL=https://url-to-license-file.pdf
SPUML_URL=https://url-to-license-file.pdf

# POLYGON TOKEN ORACLE
POLYGON_TOKEN_ORACLE_CLIENT=0x123412341234123412341234123412341234
Expand Down
45 changes: 41 additions & 4 deletions contracts/interfaces/modules/licensing/ILicensingModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,45 @@
pragma solidity ^0.8.19;

import { IModule } from "contracts/interfaces/modules/base/IModule.sol";
import { Licensing } from "contracts/lib/modules/Licensing.sol";

/// @title Licensing Module Interface
/// @notice Interface for the licensing module
/// TODO(ramarti): Fill this in.
interface ILicensingModule is IModule {}
/// @title ILicensingModule
interface ILicensingModule is IModule {

/// Emits when an IP org picks a licensing framework
/// and sets its configuration.
/// @param ipOrg address of the IP org
/// @param frameworkId the ID of the licensing framework
/// @param url to the legal document
/// @param licensorConfig the configuration of the licensor
event IpOrgLicensingFrameworkSet(
address indexed ipOrg,
string frameworkId,
string url,
Licensing.LicensorConfig licensorConfig
);

/// Emits when an IP org sets a parameter of a licensing framework.
/// @param ipOrg address of the IP org
/// @param paramTag the tag of the parameter
/// @param defaultValue the default value of the parameter
event ParameterSet(
address indexed ipOrg,
string paramTag,
bytes defaultValue
);

/// Gets the licensing framework of an IP org.
function getIpOrgLicensorConfig(address ipOrg_) external view returns (Licensing.LicensorConfig);

/// Gets the value set by an IP org for a parameter of a licensing framework.
/// If no value is set (bytes.length==0), licensors will be able to set their value.
/// @param ipOrg_ address of the IP org
/// @param paramTag_ string tag of the parameter
function getIpOrgValueForParam(
address ipOrg_,
string calldata paramTag_
) external view returns (bytes memory);


}
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import { Errors } from "contracts/lib/Errors.sol";
/// for these terms without the need of a decoder)
/// @dev must be < 32 bytes long, or they will blow up at some point
/// see https://docs.openzeppelin.com/contracts/4.x/api/utils#ShortStrings
library PIPLicensingTerms {
library SPUMLParams {
using ShortStrings for *;

string constant FRAMEWORK_ID = "SPIPL-1.0";
string constant FRAMEWORK_ID = "SPUML-1.0";
////////////////////////////////////////////////////////////////////////////
// Parameters //
////////////////////////////////////////////////////////////////////////////
Expand Down
29 changes: 10 additions & 19 deletions contracts/modules/licensing/LicensingModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,22 @@ import { ILicensingModule } from "contracts/interfaces/modules/licensing/ILicens
import { ShortStringOps } from "contracts/utils/ShortStringOps.sol";
import { BitMask } from "contracts/lib/BitMask.sol";
import { ModuleKey, LICENSING_MODULE_KEY } from "contracts/lib/modules/Module.sol";
import { SPUMLParams } from "contracts/lib/modules/SPUMLParams.sol";
import { ShortStringOps } from "contracts/utils/ShortStringOps.sol";
import { BitMask } from "contracts/lib/BitMask.sol";
import { ILicensingModule } from "contracts/interfaces/modules/licensing/ILicensingModule.sol";

/// @title Licensing module
/// @notice Story Protocol module that:
/// - Enables each IP Org to select a licensing framework fron LicensingFrameworkRepo
/// - Enables Other modules to mint License NFTs, and attach them to IPAs
/// - Enables license holders to create derivative licenses and sublicenses
/// @dev The alpha version of this module is hardcoded to use the SPIPL-1 framework
/// @dev The alpha version of this module is hardcoded to use the SPUML framework
/// Thanks to the authors of ERC-5218 for the inspiration (see https://eips.ethereum.org/EIPS/eip-5218)
contract LicensingModule is BaseModule, ILicensingModule {
using ShortStrings for *;
using FixedSet for FixedSet.ShortStringSet;

event IpOrgLicensingFrameworkSet(
address indexed ipOrg,
string frameworkId,
string url,
Licensing.LicensorConfig licensorConfig
);

event ParameterSet(
address indexed ipOrg,
string paramTag,
bytes defaultValue
);

/// @notice Holds the supported paramerter tags for each ipOrg, and the default values
/// ipOrg -> paramTag -> bytes
// TODO(ramarti): optimize for only 1 sload
Expand Down Expand Up @@ -78,7 +69,7 @@ contract LicensingModule is BaseModule, ILicensingModule {
return _licensorConfig[ipOrg_];
}

function getDefaultValueForParam(
function getIpOrgValueForParam(
address ipOrg_,
string calldata paramTag_
) external view returns (bytes memory) {
Expand Down Expand Up @@ -271,20 +262,20 @@ contract LicensingModule is BaseModule, ILicensingModule {
continue;
}
// If param is not empty, check for Derivative license flags
if (ShortStringOps._equal(paramDef.tag, PIPLicensingTerms.DERIVATIVES_ALLOWED)) {
if (ShortStringOps._equal(paramDef.tag, SPUMLParams.DERIVATIVES_ALLOWED)) {
derivativesAllowed = abi.decode(resultValue, (bool));
} else if (ShortStringOps._equal(paramDef.tag, PIPLicensingTerms.DERIVATIVES_ALLOWED_OPTIONS)) {
} else if (ShortStringOps._equal(paramDef.tag, SPUMLParams.DERIVATIVES_ALLOWED_OPTIONS)) {
uint256 derivativeIndexMask = abi.decode(
resultValue,
(uint256)
);
derivativeNeedsApproval = BitMask._isSet(
derivativeIndexMask,
PIPLicensingTerms.ALLOWED_WITH_APPROVAL_INDEX
SPUMLParams.ALLOWED_WITH_APPROVAL_INDEX
);
isReciprocal = BitMask._isSet(
derivativeIndexMask,
PIPLicensingTerms.ALLOWED_WITH_RECIPROCAL_LICENSE_INDEX
SPUMLParams.ALLOWED_WITH_RECIPROCAL_LICENSE_INDEX
);
}
}
Expand Down
30 changes: 15 additions & 15 deletions deployment-11155111.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
{
"main": {
"AccessControlSingleton-Impl": "0x60a56aB6360572bCFFB7d724a79A9C6cE868c756",
"AccessControlSingleton-Proxy": "0xEFfd9E4194aE9C1313A5297a572D70C70343Ed04",
"IPAssetRegistry": "0x468a2220f6b1dCaAe138142C64cd643179893C6e",
"IPOrgController-Impl": "0x7DE573872B80D2a2Dc67dC3e3E7ea0F4DA95c23d",
"IPOrgController-Proxy": "0xB8F98568FA4dc1122096f250468B16194Af102b7",
"LicenseRegistry": "0xFFdB0db0EA5e646dD50BFfc7A53f85e198a5118a",
"LicensingFrameworkRepo": "0x7bF69727760d1d68D5Ea8ecd983dd2d520C78cbf",
"LicensingModule": "0x5c19113eBb0C944A023A8B37265FDdB186362872",
"MockERC721": "0x70603c7413A634ae34fAF0903FC9F8F60D218dA4",
"ModuleRegistry": "0xCa3296538010aad4733bD80ED426dcFbeDe3183C",
"PolygonTokenHook": "0x7799333d6C2eea0119a221665996C08065A5E34a",
"RegistrationModule": "0xfA0B488cD7a07794085aB4BB22969BEcE97DEB2F",
"RelationshipModule": "0xbB0db413b72b90503Aa465Ed1d2b5ABDBF7949B0",
"StoryProtocol": "0x5B4FE4484fb347cA3aA4F47B02197F019fdde18E",
"TokenGatedHook": "0xBE0e7f37eaa32c9a5D727af48D70Eed6155071B0"
"AccessControlSingleton-Impl": "0xCF723c4072183965d25aFc1c7589E6008f054b12",
"AccessControlSingleton-Proxy": "0xB8E15a0CC5695165C7a1ABbA40B55fE04061DBd0",
"IPAssetRegistry": "0xEd05dcB9EF77DB02d831377865Ba374C00228C3F",
"IPOrgController-Impl": "0x46e4646266C113D65De1899A145F1e7749E93388",
"IPOrgController-Proxy": "0x8492e251305CdE6d4dab54240551588D7a91BD23",
"LicenseRegistry": "0x5e17aC4Ba7995Fc9335F6187d4282D9982918F68",
"LicensingFrameworkRepo": "0xc0C25d92b6C71fcdC1dE84C37bd623dD7a0b5e05",
"LicensingModule": "0x20B4b22Ddb3b5043938454544eD6E3b77F23676F",
"MockERC721": "0x9505DF44eEa46b1a0BBEa1E76839815B3532FF38",
"ModuleRegistry": "0xc42981fc4AeAB64B626627c0173f19DAc04F06e5",
"PolygonTokenHook": "0x43d3EA92Ef75a3DA352a205F3258c6b425b1fd8C",
"RegistrationModule": "0x1FA57D55E45B898b337c05E7198f0f72FFD198b1",
"RelationshipModule": "0xBe14Ce44659d123759E5B7786165eC3a91c27FDA",
"StoryProtocol": "0x3af4Fc16c28690EDd3A590486c8B37161afCf9c7",
"TokenGatedHook": "0xa76c8360b49c4448Ea9a21Ce57D9197B4E8F44D0"
}
}
8 changes: 4 additions & 4 deletions script/foundry/deployment/Main.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import "contracts/modules/licensing/LicenseRegistry.sol";
import "contracts/modules/licensing/LicensingFrameworkRepo.sol";
import "contracts/modules/licensing/LicensingModule.sol";
import "contracts/lib/modules/Licensing.sol";
import "contracts/lib/modules/PIPLicensingTerms.sol";
import "contracts/lib/modules/SPUMLParams.sol";
import { PolygonToken } from "contracts/lib/hooks/PolygonToken.sol";
import { Create2 } from "@openzeppelin/contracts/utils/Create2.sol";
import { Hook } from "contracts/lib/hooks/Hook.sol";
Expand Down Expand Up @@ -383,10 +383,10 @@ contract Main is Script, BroadcastManager, JsonDeploymentHandler, ProxyHelper {
);

// CONFIG LICENSING MODULE
Licensing.ParamDefinition[] memory paramDefs = PIPLicensingTerms._getParamDefs();
Licensing.ParamDefinition[] memory paramDefs = SPUMLParams._getParamDefs();
Licensing.SetFramework memory framework = Licensing.SetFramework({
id: PIPLicensingTerms.FRAMEWORK_ID,
textUrl: vm.envString("PIPL_URL"),
id: SPUMLParams.FRAMEWORK_ID,
textUrl: vm.envString("SPUML_URL"),
paramDefs: paramDefs
});
LicensingFrameworkRepo(licensingFrameworkRepo).addFramework(framework);
Expand Down
24 changes: 12 additions & 12 deletions test/foundry/modules/licensing/LicenseRegistry.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Licensing } from "contracts/lib/modules/Licensing.sol";
import { IPAsset } from "contracts/lib/IPAsset.sol";
import { BaseTest } from "test/foundry/utils/BaseTest.sol";
import { Errors } from "contracts/lib/Errors.sol";
import { PIPLicensingTerms } from "contracts/lib/modules/PIPLicensingTerms.sol";
import { SPUMLParams } from "contracts/lib/modules/SPUMLParams.sol";
import { ShortString, ShortStrings } from "@openzeppelin/contracts/utils/ShortStrings.sol";
import { BitMask } from "contracts/lib/BitMask.sol";

Expand Down Expand Up @@ -41,27 +41,27 @@ contract LicenseRegistryTest is BaseTest {
channels[0] = "test1".toShortString();
channels[1] = "test2".toShortString();
params.push(Licensing.ParamValue({
tag: PIPLicensingTerms.CHANNELS_OF_DISTRIBUTION.toShortString(),
tag: SPUMLParams.CHANNELS_OF_DISTRIBUTION.toShortString(),
value: abi.encode(channels)
}));
params.push(Licensing.ParamValue({
tag: PIPLicensingTerms.ATTRIBUTION.toShortString(),
tag: SPUMLParams.ATTRIBUTION.toShortString(),
value: ""// unset
}));
params.push(Licensing.ParamValue({
tag: PIPLicensingTerms.DERIVATIVES_ALLOWED.toShortString(),
tag: SPUMLParams.DERIVATIVES_ALLOWED.toShortString(),
value: abi.encode(allowsDerivatives)
}));
uint8[] memory indexes = new uint8[](2);
if (derivativesWithApproval) {
indexes[0] = PIPLicensingTerms.ALLOWED_WITH_APPROVAL_INDEX;
indexes[0] = SPUMLParams.ALLOWED_WITH_APPROVAL_INDEX;
}
if (reciprocal) {
indexes[1] = PIPLicensingTerms.ALLOWED_WITH_RECIPROCAL_LICENSE_INDEX;
indexes[1] = SPUMLParams.ALLOWED_WITH_RECIPROCAL_LICENSE_INDEX;
}
uint256 derivativeOptions = BitMask._convertToMask(indexes);
params.push(Licensing.ParamValue({
tag: PIPLicensingTerms.DERIVATIVES_ALLOWED_OPTIONS.toShortString(),
tag: SPUMLParams.DERIVATIVES_ALLOWED_OPTIONS.toShortString(),
value: abi.encode(derivativeOptions)
}));
for(uint256 i = 0; i < params.length; i++) {
Expand All @@ -70,7 +70,7 @@ contract LicenseRegistryTest is BaseTest {
}

Licensing.LicensingConfig memory config = Licensing.LicensingConfig({
frameworkId: PIPLicensingTerms.FRAMEWORK_ID,
frameworkId: SPUMLParams.FRAMEWORK_ID,
params: params,
licensor: licensorConfig
});
Expand All @@ -85,10 +85,10 @@ contract LicenseRegistryTest is BaseTest {
(ipaId_1, ) = _createIpAsset(ipaOwner, 1, bytes(""));
(ipaId_2, ) = _createIpAsset(ipaOwner, 1, bytes(""));

Licensing.ParamDefinition[] memory paramDefs = PIPLicensingTerms
Licensing.ParamDefinition[] memory paramDefs = SPUMLParams
._getParamDefs();
Licensing.SetFramework memory framework = Licensing.SetFramework({
id: PIPLicensingTerms.FRAMEWORK_ID,
id: SPUMLParams.FRAMEWORK_ID,
textUrl: "text_url",
paramDefs: paramDefs
});
Expand Down Expand Up @@ -354,7 +354,7 @@ contract LicenseRegistryTest is BaseTest {
1
);
inputParams[0] = Licensing.ParamValue({
tag: PIPLicensingTerms.ATTRIBUTION.toShortString(),
tag: SPUMLParams.ATTRIBUTION.toShortString(),
value: abi.encode(true)
});
return inputParams;
Expand Down Expand Up @@ -410,7 +410,7 @@ contract LicenseRegistryTest is BaseTest {
assertEq(license.ipOrg, address(ipOrg), "ipOrg B");
assertEq(
license.frameworkId.toString(),
PIPLicensingTerms.FRAMEWORK_ID
SPUMLParams.FRAMEWORK_ID
);
assertEq(license.ipaId, licenseRegistry.getIpaId(licenseId), "ipaId A");
assertEq(license.ipaId, expectedIpaId, "ipaId B");
Expand Down
6 changes: 3 additions & 3 deletions test/foundry/modules/licensing/LicensingModule.Config.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -120,15 +120,15 @@ contract LicensingModuleConfigTest is BaseTest {
uint8(Licensing.LicensorConfig.IpOrgOwnerAlways)
);
assertEq(
licensingModule.getDefaultValueForParam(address(ipOrg), "TEST_TAG_1"),
licensingModule.getIpOrgValueForParam(address(ipOrg), "TEST_TAG_1"),
abi.encode(true)
);
assertEq(
licensingModule.getDefaultValueForParam(address(ipOrg), "TEST_TAG_2"),
licensingModule.getIpOrgValueForParam(address(ipOrg), "TEST_TAG_2"),
abi.encode(222)
);
assertEq(
licensingModule.getDefaultValueForParam(address(ipOrg), "TEST_TAG_3"),
licensingModule.getIpOrgValueForParam(address(ipOrg), "TEST_TAG_3"),
abi.encode(ssValue)
);
}
Expand Down
26 changes: 13 additions & 13 deletions test/foundry/modules/licensing/LicensingModule.Licensing.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Licensing } from "contracts/lib/modules/Licensing.sol";
import { IPAsset } from "contracts/lib/IPAsset.sol";
import { BaseTest } from "test/foundry/utils/BaseTest.sol";
import { Errors } from "contracts/lib/Errors.sol";
import { PIPLicensingTerms } from "contracts/lib/modules/PIPLicensingTerms.sol";
import { SPUMLParams } from "contracts/lib/modules/SPUMLParams.sol";
import { BitMask } from "contracts/lib/BitMask.sol";
import { ShortString, ShortStrings } from "@openzeppelin/contracts/utils/ShortStrings.sol";

Expand All @@ -33,27 +33,27 @@ contract LicensingModuleLicensingTest is BaseTest {
channels[0] = "test1".toShortString();
channels[1] = "test2".toShortString();
ipOrgParams.push(Licensing.ParamValue({
tag: PIPLicensingTerms.CHANNELS_OF_DISTRIBUTION.toShortString(),
tag: SPUMLParams.CHANNELS_OF_DISTRIBUTION.toShortString(),
value: abi.encode(channels)
}));
ipOrgParams.push(Licensing.ParamValue({
tag: PIPLicensingTerms.ATTRIBUTION.toShortString(),
tag: SPUMLParams.ATTRIBUTION.toShortString(),
value: ""// unset
}));
ipOrgParams.push(Licensing.ParamValue({
tag: PIPLicensingTerms.DERIVATIVES_ALLOWED.toShortString(),
tag: SPUMLParams.DERIVATIVES_ALLOWED.toShortString(),
value: abi.encode(allowsDerivatives)
}));
uint8[] memory indexes = new uint8[](2);
if (derivativesWithApproval) {
indexes[0] = PIPLicensingTerms.ALLOWED_WITH_APPROVAL_INDEX;
indexes[0] = SPUMLParams.ALLOWED_WITH_APPROVAL_INDEX;
}
if (reciprocal) {
indexes[1] = PIPLicensingTerms.ALLOWED_WITH_RECIPROCAL_LICENSE_INDEX;
indexes[1] = SPUMLParams.ALLOWED_WITH_RECIPROCAL_LICENSE_INDEX;
}
uint256 derivativeOptions = BitMask._convertToMask(indexes);
ipOrgParams.push(Licensing.ParamValue({
tag: PIPLicensingTerms.DERIVATIVES_ALLOWED_OPTIONS.toShortString(),
tag: SPUMLParams.DERIVATIVES_ALLOWED_OPTIONS.toShortString(),
value: abi.encode(derivativeOptions)
}));
console.log("withFrameworkConfig:");
Expand All @@ -63,7 +63,7 @@ contract LicensingModuleLicensingTest is BaseTest {
}

Licensing.LicensingConfig memory config = Licensing.LicensingConfig({
frameworkId: PIPLicensingTerms.FRAMEWORK_ID,
frameworkId: SPUMLParams.FRAMEWORK_ID,
params: ipOrgParams,
licensor: licensorConfig
});
Expand All @@ -77,10 +77,10 @@ contract LicensingModuleLicensingTest is BaseTest {
(ipaId_1, ) = _createIpAsset(ipaOwner, 1, bytes(""));
(ipaId_2, ) = _createIpAsset(ipaOwner, 1, bytes(""));

Licensing.ParamDefinition[] memory paramDefs = PIPLicensingTerms
Licensing.ParamDefinition[] memory paramDefs = SPUMLParams
._getParamDefs();
Licensing.SetFramework memory framework = Licensing.SetFramework({
id: PIPLicensingTerms.FRAMEWORK_ID,
id: SPUMLParams.FRAMEWORK_ID,
textUrl: "text_url",
paramDefs: paramDefs
});
Expand Down Expand Up @@ -189,7 +189,7 @@ contract LicensingModuleLicensingTest is BaseTest {
assertEq(license.revoker, licensingModule.DEFAULT_REVOKER());
assertEq(license.licensor, ipOrg.owner());
assertEq(license.ipOrg, address(ipOrg));
assertEq(license.frameworkId.toString(), PIPLicensingTerms.FRAMEWORK_ID);
assertEq(license.frameworkId.toString(), SPUMLParams.FRAMEWORK_ID);
assertEq(license.ipaId, 0, "ipaId");
assertEq(license.parentLicenseId, parentLicenseId);
Licensing.ParamValue[] memory parentParams = licenseRegistry.getParams(parentLicenseId);
Expand All @@ -213,7 +213,7 @@ contract LicensingModuleLicensingTest is BaseTest {
1
);
inputParams[0] = Licensing.ParamValue({
tag: PIPLicensingTerms.ATTRIBUTION.toShortString(),
tag: SPUMLParams.ATTRIBUTION.toShortString(),
value: abi.encode(true)
});
return inputParams;
Expand Down Expand Up @@ -269,7 +269,7 @@ contract LicensingModuleLicensingTest is BaseTest {
assertEq(license.ipOrg, address(ipOrg), "ipOrg B");
assertEq(
license.frameworkId.toString(),
PIPLicensingTerms.FRAMEWORK_ID
SPUMLParams.FRAMEWORK_ID
);
assertEq(license.ipaId, licenseRegistry.getIpaId(licenseId), "ipaId A");
assertEq(license.ipaId, expectedIpaId, "ipaId B");
Expand Down

0 comments on commit df2c14f

Please sign in to comment.