Skip to content

Commit

Permalink
Refactor licensing (#170)
Browse files Browse the repository at this point in the history
* configure ipOrg license

* terms repository, framework config

* wip

* introducing hooks for terms

* short string helpers

* terms hook

* licensing module, config ipOrg licensing framework

* cleanup

* IPA goes into IPAsset library

* deleted old interfaces

* delete old contracts

* refactored configuration to be purely terms based, testing creating licenses

* refactor TermsConfig, added FixedSet

* create root license

* minting LNFT

* refactor licensing term libs

* fix test

* refactor to account for enshrined share alike

* refactored IPA_LICENSE and SUBLICENSE_OF back into the licensing module

* simplified terms data

* add comments:

* more comments

* fixed comments and added access control to license registry

* import order

* todo hook key providing

* remove hardhat tests

* fixing compilation errors

* introducing ipa registration module

* temporally remove tests

---------

Co-authored-by: Raul <[email protected]>
  • Loading branch information
Ramarti and Raul authored Nov 16, 2023
1 parent c1dee85 commit cfb2a85
Show file tree
Hide file tree
Showing 48 changed files with 2,125 additions and 2,581 deletions.
17 changes: 0 additions & 17 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,20 +67,3 @@ jobs:
# run:
# forge coverage --report lcov --report summary
# id: forge-code-coverage

hardhat-test:
strategy:
fail-fast: true

name: Hardhat Unit Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
submodules: recursive
- name: Environment
uses: actions/setup-node@v3
- name: Test
uses: ambersun1234/[email protected]
with:
network: hardhat
22 changes: 6 additions & 16 deletions contracts/IPAssetRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,17 @@ import { IModuleRegistry } from "contracts/interfaces/modules/IModuleRegistry.so
import { IIPOrg } from "contracts/interfaces/ip-org/IIPOrg.sol";
import { ModuleRegistryKeys } from "contracts/lib/modules/ModuleRegistryKeys.sol";
import { Errors } from "contracts/lib/Errors.sol";
import { IPAsset } from "contracts/lib/IPAsset.sol";

/// @title Global IP Asset Registry
/// @notice The source of truth for IP on Story Protocol.
contract IPAssetRegistry is IIPAssetRegistry {

/// @notice Core attributes that make up an IP Asset.
struct IPA {
string name; // Human-readable identifier for the IP asset.
uint64 ipAssetType; // Numerical code corresponding to IP type (e.g. patent, copyright, etc.)
address registrant; // Address of the initial registrant of the IP asset.
uint8 status; // Current status of the IP asset (e.g. active, expired, etc.)
address ipOrg; // Address of the governing entity of the IP asset.
bytes32 hash; // A unique content hash of the IP asset for preserving integrity.
uint64 registrationDate; // Timestamp for which the IP asset was first registered.
}

/// @notice Used for fetching modules associated with an IP asset.
IModuleRegistry public immutable MODULE_REGISTRY;

/// @notice Mapping from IP asset ids to registry records.
mapping(uint256 => IPA) internal _ipAssets;
mapping(uint256 => IPAsset.IPA) internal _ipAssets;

/// @notice Tracks the total number of IP Assets in existence.
/// TODO(leeren) Switch from numerical ids to a universal namehash.
Expand Down Expand Up @@ -73,10 +63,10 @@ contract IPAssetRegistry is IIPAssetRegistry {
// Crate a new IP asset with the provided IP attributes.
ipAssetId = totalSupply++;
uint64 registrationDate = uint64(block.timestamp);
_ipAssets[ipAssetId] = IPA({
_ipAssets[ipAssetId] = IPAsset.IPA({
name: name_,
ipAssetType: ipAssetType_,
status: 0, // TODO(ramarti): Define status types.
status: 1, // TODO(ramarti): Define status types.
registrant: registrant_,
ipOrg: msg.sender,
hash: hash_,
Expand Down Expand Up @@ -132,8 +122,8 @@ contract IPAssetRegistry is IIPAssetRegistry {

/// @notice Returns all attributes related to an IP asset.
/// @param ipAssetId_ The id of the IP asset being queried for.
function ipAsset(uint256 ipAssetId_) public view returns (IPA memory) {
function ipAsset(uint256 ipAssetId_) public view returns (IPAsset.IPA memory) {
return _ipAssets[ipAssetId_];
}

}
}
86 changes: 82 additions & 4 deletions contracts/StoryProtocol.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { ModuleRegistry } from "contracts/modules/ModuleRegistry.sol";
import { LibRelationship } from "contracts/lib/modules/LibRelationship.sol";
import { Registration } from "contracts/lib/modules/Registration.sol";
import { ModuleRegistryKeys } from "contracts/lib/modules/ModuleRegistryKeys.sol";
import { Licensing } from "contracts/lib/modules/Licensing.sol";

contract StoryProtocol {

Expand Down Expand Up @@ -82,10 +83,6 @@ contract StoryProtocol {
bytes[] calldata preHooksData_,
bytes[] calldata postHooksData_
) public returns (uint256, uint256) {
bytes memory encodedParams = abi.encode(
Registration.REGISTER_IP_ASSET,
abi.encode(params_)
);
bytes memory result = MODULE_REGISTRY.execute(
IIPOrg(ipOrg_),
msg.sender,
Expand Down Expand Up @@ -170,4 +167,85 @@ contract StoryProtocol {
);
return abi.decode(result, (uint256));
}

////////////////////////////////////////////////////////////////////////////
// Licensing //
////////////////////////////////////////////////////////////////////////////

/// Allows an IPOrg to configure its licensing framework (collection of commercial and non-commercial terms)
/// @param ipOrg_ the ipOrg address
/// @param framework_ licensing term id array, and matching term data array to configure them
function configureIpOrgLicensing(
address ipOrg_,
Licensing.FrameworkConfig calldata framework_
) external {
MODULE_REGISTRY.configure(
IIPOrg(ipOrg_),
msg.sender,
ModuleRegistryKeys.LICENSING_MODULE,
abi.encode(Licensing.LICENSING_FRAMEWORK_CONFIG, abi.encode(framework_))
);
}

/// Creates a tradeable License NFT in License Registry.
/// @param ipOrg_ the ipOrg address
/// @param params_ LicenseCreation params
/// @param licensee_ address of the licensee (and owner of the NFT)
/// @param preHooksData_ Hooks data to embed with the registration pre-call.
/// @param postHooksData_ Hooks data to embed with the registration post-call.
/// @return id of the created license
function createLicenseNft(
address ipOrg_,
Licensing.LicenseCreation calldata params_,
address licensee_,
bytes[] calldata preHooksData_,
bytes[] calldata postHooksData_
) external returns (uint256) {
bytes memory params = abi.encode(
params_,
Licensing.LicenseeType.LNFTHolder,
abi.encode(licensee_)
);
return abi.decode(
MODULE_REGISTRY.execute(
IIPOrg(ipOrg_),
msg.sender,
ModuleRegistryKeys.LICENSING_MODULE,
params,
preHooksData_,
postHooksData_
),
(uint256)
);
}

/// Creates a License bound to a certain IPA. It's not an NFT, the licensee will be the owner of the IPA.
/// @param ipOrg_ the ipOrg address
/// @param params_ LicenseCreation params
/// @param ipaId_ id of the bound IPA
/// @param preHooksData_ Hooks data to embed with the registration pre-call.
/// @param postHooksData_ Hooks data to embed with the registration post-call.
/// @return id of the created license
function createIpaBoundLicense(
address ipOrg_,
Licensing.LicenseCreation calldata params_,
uint256 ipaId_,
bytes[] calldata preHooksData_,
bytes[] calldata postHooksData_
) external returns (uint256) {
bytes memory params = abi.encode(
params_,
Licensing.LicenseeType.BoundToIpa,
abi.encode(ipaId_)
);
return abi.decode( MODULE_REGISTRY.execute(
IIPOrg(ipOrg_),
msg.sender,
ModuleRegistryKeys.LICENSING_MODULE,
params,
preHooksData_,
postHooksData_
),
(uint256));
}
}
1 change: 0 additions & 1 deletion contracts/access-control/AccessControlled.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { IAccessControlled } from "contracts/interfaces/access-control/IAccessCo
import { IAccessControl } from "@openzeppelin/contracts/access/IAccessControl.sol";
// solhint-disable-next-line max-line-length
import { ERC165CheckerUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165CheckerUpgradeable.sol";
import { UnsupportedInterface } from "../errors/General.sol";

abstract contract AccessControlled is IAccessControlled {
using ERC165CheckerUpgradeable for address;
Expand Down
11 changes: 0 additions & 11 deletions contracts/errors/General.sol

This file was deleted.

7 changes: 6 additions & 1 deletion contracts/interfaces/modules/base/IModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ interface IModule {
/// @param ipOrg_ address of the IPOrg or zero address
/// @param caller_ address requesting the execution
/// @param params_ encoded params for module configuration
function configure(IIPOrg ipOrg_, address caller_, bytes calldata params_) external;
/// @return result of the module configuration
function configure(
IIPOrg ipOrg_,
address caller_,
bytes calldata params_
) external returns (bytes memory result);

}
150 changes: 0 additions & 150 deletions contracts/interfaces/modules/licensing/IERC5218.sol

This file was deleted.

18 changes: 0 additions & 18 deletions contracts/interfaces/modules/licensing/ILicenseRegistry.sol

This file was deleted.

Loading

0 comments on commit cfb2a85

Please sign in to comment.