Skip to content

Commit

Permalink
Refactors to support global IP asset identification (#129)
Browse files Browse the repository at this point in the history
* Refactors to support global IP asset identification

* Removes console logs

* Finalizes initial refactor

* Fixes import ordering
  • Loading branch information
leeren authored Oct 30, 2023
1 parent e82fc80 commit a7c3db7
Show file tree
Hide file tree
Showing 65 changed files with 1,707 additions and 1,639 deletions.
139 changes: 0 additions & 139 deletions contracts/FranchiseRegistry.sol

This file was deleted.

116 changes: 116 additions & 0 deletions contracts/IPAssetOrgFactory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.13;

import { Clones } from '@openzeppelin/contracts/proxy/Clones.sol';
import { IPAsset } from "contracts/lib/IPAsset.sol";
import { AccessControl } from "contracts/lib/AccessControl.sol";
import { Errors } from "contracts/lib/Errors.sol";
import { AccessControlledUpgradeable } from "./access-control/AccessControlledUpgradeable.sol";
import { LicenseRegistry } from "contracts/modules/licensing/LicenseRegistry.sol";
import { IIPAssetOrgFactory } from "contracts/interfaces/IIPAssetOrgFactory.sol";
import { IPAssetOrg } from "contracts/ip-assets/IPAssetOrg.sol";
import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";

/// @notice IP Asset Organization Factory Contract
/// TODO(ramarti): Extend the base hooks contract utilized by SP modules.
contract IPAssetOrgFactory is
UUPSUpgradeable,
AccessControlledUpgradeable,
IIPAssetOrgFactory
{

/// @notice Base template implementation contract used for new IP Asset Org creation.
address public immutable IP_ASSET_ORG_IMPL = address(new IPAssetOrg());

string private constant _VERSION = "0.1.0";

// TODO(@leeren): Fix storage hash
// keccak256(bytes.concat(bytes32(uint256(keccak256("story-protocol.ip-asset-org-factory.storage")) - 1)))
bytes32 private constant _STORAGE_LOCATION = 0x1b0b8fa444ff575656111a4368b8e6a743b70cbf31ffb9ee2c7afe1983f0e378;

/// @custom:storage-location erc7201:story-protocol.ip-asset-org-factory.storage
// TODO: Extend IP asset org storage to support other relevant configurations
struct IPAssetOrgFactoryStorage {
/// @dev Tracks mappings from ipAssetOrg to whether they were registered.
mapping(address => bool) registered;
}

/// @notice Checks if an address is a valid IP Asset Organization.
/// @param ipAssetOrg_ the address to check
/// @return true if `ipAssetOrg_` is a valid IP Asset Organization, false otherwise
function isIpAssetOrg(
address ipAssetOrg_
) external view returns (bool) {
IPAssetOrgFactoryStorage storage $ = _getIpAssetOrgFactoryStorage();
return $.registered[ipAssetOrg_];
}

/// @notice Returns the current version of the factory contract.
function version() external pure override returns (string memory) {
return _VERSION;
}


/// @notice Registers a new ipAssetOrg for IP asset collection management.
/// @param params_ Parameters required for ipAssetOrg creation.
/// TODO: Converge on core primitives utilized for ipAssetOrg management.
/// TODO: Add ipAssetOrg-wide module configurations to the registration process.
// TODO: Remove registry
function registerIPAssetOrg(
IPAsset.RegisterIPAssetOrgParams calldata params_
) public returns (address) {
address ipAssetOrg = Clones.clone(IP_ASSET_ORG_IMPL);
IPAssetOrg(ipAssetOrg).initialize(IPAsset.InitIPAssetOrgParams({
registry: params_.registry,
owner: msg.sender,
name: params_.name,
symbol: params_.symbol,
description: params_.description,
licensingModule: params_.licensingModule,
collectModule: params_.collectModule
}));

/// TODO(ramarti): Switch to global licensing registry.
LicenseRegistry licenseRegistry = new LicenseRegistry(
ipAssetOrg,
string.concat("Licenses for ", params_.name),
string.concat("sl", params_.symbol)
);
IPAssetOrg(ipAssetOrg).setLicenseRegistry(address(licenseRegistry));

// Set the registration status of the IP Asset Org to be true.
IPAssetOrgFactoryStorage storage $ = _getIpAssetOrgFactoryStorage();
$.registered[ipAssetOrg] = true;

emit IPAssetOrgRegistered(
msg.sender,
ipAssetOrg,
params_.name,
params_.symbol,
params_.tokenURI
);
return ipAssetOrg;

}

/// @notice Initializes the IPAssetOrgFactory contract.
/// @param accessControl_ Address of the contract responsible for access control.
function initialize(address accessControl_) public initializer {
__UUPSUpgradeable_init();
__AccessControlledUpgradeable_init(accessControl_);
}

function _authorizeUpgrade(
address newImplementation_
) internal virtual override onlyRole(AccessControl.UPGRADER_ROLE) {}

function _getIpAssetOrgFactoryStorage()
private
pure
returns (IPAssetOrgFactoryStorage storage $)
{
assembly {
$.slot := _STORAGE_LOCATION
}
}
}
63 changes: 63 additions & 0 deletions contracts/IPAssetRegistry.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.19;

import { IIPAssetRegistry } from "contracts/interfaces/IIPAssetRegistry.sol";

/// @title IP Asset Registry
/// @notice The source of truth for IP on Story Protocol.
// TO-DO(@leeren): Add authorization around IP Asset registration and ownership transferring.
// TO-DO(ramarti): Add authorization around IP Asset Org transfer of IP Assets.
contract IPAssetRegistry is IIPAssetRegistry {

/// @notice Core attributes that make up an IP Asset.
// TO-DO: Add other core IP Asset primitives (namely module linking).
struct IPAsset {
address owner; // TO-DO: Consider removing this in the future.
address ipAssetOrg;
}

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

/// @notice Tracks the total number of IP Assets in existence.
uint256 numIPAssets = 0;

/// @notice Registers a new IP Asset.
/// @param owner_ The address of the IP Asset.
/// @param ipAssetOrg_ The address of the IP Asset Org.
// TO-DO(@leeren): Add registration authorization (likely based around IPAssetOrg enrollment).
// TO_DO(ramarti): Add module registration via resolver / registry.
function register(address owner_, address ipAssetOrg_) public returns (uint256) {
uint256 ipAssetId = numIPAssets++;
ipAssets[ipAssetId] = IPAsset({
owner: owner_,
ipAssetOrg: ipAssetOrg_
});

emit IPAssetRegistered(ipAssetId, owner_, ipAssetOrg_);
return ipAssetId;
}

function setOwner(uint256 ipAssetId_, address owner_) public {
ipAssets[ipAssetId_].owner = owner_;
emit OwnerTransferred(ipAssetId_, owner_);
}

function setIpAssetOrg(uint256 ipAssetId_, address ipAssetOrg_) public {
ipAssets[ipAssetId_].ipAssetOrg = ipAssetOrg_;
emit OrgTransferred(ipAssetId_, ipAssetOrg_);
}

/// @notice Gets the IP Asset Org that administers a specific IP Asset.
/// @param ipAssetId_ The id of the IP Asset being queried.
function ipAssetOrg(uint256 ipAssetId_) public returns (address) {
return ipAssets[ipAssetId_].ipAssetOrg;
}

/// @notice Gets the owner of a specific IP Asset.
/// @param ipAssetId_ The id of the IP Asset being queried.
function ipAssetOwner(uint256 ipAssetId_) public returns (address) {
return ipAssets[ipAssetId_].owner;
}

}
20 changes: 20 additions & 0 deletions contracts/interfaces/IIPAssetOrgFactory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.19;

import { IVersioned } from "./utils/IVersioned.sol";
import { IPAsset } from "contracts/lib/IPAsset.sol";

interface IIPAssetOrgFactory is IVersioned {

event IPAssetOrgRegistered(
address owner_,
address ipAssetOrg_,
string name_,
string symbol_,
string tokenURI_
);

function registerIPAssetOrg(IPAsset.RegisterIPAssetOrgParams calldata params_) external returns(address);

function isIpAssetOrg(address ipAssetOrg_) external view returns (bool);
}
24 changes: 24 additions & 0 deletions contracts/interfaces/IIPAssetRegistry.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { IPAsset } from "contracts/lib/IPAsset.sol";

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.19;

interface IIPAssetRegistry {

event IPAssetRegistered(
uint256 ipAssetId_,
address owner_,
address ipAssetOrg_
);

event OrgTransferred(
uint256 indexed ipAssetId_,
address indexed owner_
);

event OwnerTransferred(
uint256 indexed ipAssetId_,
address indexed owner_
);

}
Loading

0 comments on commit a7c3db7

Please sign in to comment.