Skip to content

Commit

Permalink
Adds detailed contract documentation (#203)
Browse files Browse the repository at this point in the history
* Adds detailed documentation for major contracts

* Prevent complaining about max line
leeren authored Nov 28, 2023
1 parent 09ab475 commit 978580f
Showing 10 changed files with 46 additions and 36 deletions.
7 changes: 6 additions & 1 deletion contracts/IPAssetRegistry.sol
Original file line number Diff line number Diff line change
@@ -9,7 +9,12 @@ import { ModuleRegistryKeys } from "contracts/lib/modules/ModuleRegistryKeys.sol
import { Errors } from "contracts/lib/Errors.sol";

/// @title Global IP Asset Registry
/// @notice The source of truth for IP on Story Protocol.
/// @notice The global IP Asset Registry (GIPR) acts as the source of truth for IP
/// attribution in Story Protocol. All IP must be registered through a
/// protocol-approved registration module, which as part of the process will
/// create a record in the GIPR. Note that the GIPR only defines the core
/// attributes related to an IP asset - all other attributes, which will be
/// specific for a given module, will be queried through the module registry.
contract IPAssetRegistry is IIPAssetRegistry {

/// @notice Core attributes that make up an IP Asset.
7 changes: 7 additions & 0 deletions contracts/StoryProtocol.sol
Original file line number Diff line number Diff line change
@@ -14,6 +14,13 @@ import { Licensing } from "contracts/lib/modules/Licensing.sol";
import { FixedSet } from "contracts/utils/FixedSet.sol";
import { Multicall } from "@openzeppelin/contracts/utils/Multicall.sol";

/// @title Story Protocol Gateway Contract
/// @notice The Story Protocol contract acts as a global gateway for calling all
/// protocol-standardized IP actions (based on their enrolled modules).
/// Most functions can be solely executed through this contract, as it will
/// be actively maintained and upgraded to support all standardized modules.
/// In the future, for more customized logic, IP Orgs may choose to create
/// their own frontend contracts (gateways) for IP interaction.
contract StoryProtocol is Multicall {

IIPOrgController public immutable IP_ORG_CONTROLLER;
11 changes: 6 additions & 5 deletions contracts/access-control/AccessControlSingleton.sol
Original file line number Diff line number Diff line change
@@ -9,12 +9,13 @@ import { Multicall } from "@openzeppelin/contracts/utils/Multicall.sol";
import { AccessControlUpgradeable } from "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";

/// @notice AccessControlSingleton contract. Manages protocol admin keys. Other contracts might inherit
/// AccessControlled or its upgradeable version to use the onlyRole modifier.
/// TODO: Evaluate making this contract AccessControlEnumerableUpgradeable so it could enforce unique roles
/// (as in only 1 address can have a role at a time)
/// @title Access Control Singleton
/// @notice This contract serves as the global source of truth for role-based authorization.
/// Contracts that inherit the AccessControlled contract or its upgradable variant
/// are may be granted granular access to certain roles by utilizing the `onlyRole`
/// modifier with the required role input as a parameter.
contract AccessControlSingleton is
AccessControlUpgradeable,
AccessControlUpgradeable,
UUPSUpgradeable,
Multicall,
IVersioned
5 changes: 5 additions & 0 deletions contracts/access-control/AccessControlled.sol
Original file line number Diff line number Diff line change
@@ -9,6 +9,9 @@ import { IAccessControl } from "@openzeppelin/contracts/access/IAccessControl.so
// solhint-disable-next-line max-line-length
import { ERC165CheckerUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165CheckerUpgradeable.sol";

/// @title Access Controlled Contract
/// @notice This contract is to be inherited by any protocol components that require granular
/// roles for execution, as defined by the Access Control Singleton contract.
abstract contract AccessControlled is IAccessControlled {
using ERC165CheckerUpgradeable for address;

@@ -23,6 +26,8 @@ abstract contract AccessControlled is IAccessControlled {
_;
}

/// @notice Instantiates a new Access Controlled contract.
/// @param accessControl_ The global Access Control Singleton contract address.
constructor(address accessControl_) {
if (!accessControl_.supportsInterface(type(IAccessControl).interfaceId))
revert Errors.UnsupportedInterface("IAccessControl");
5 changes: 5 additions & 0 deletions contracts/access-control/AccessControlledUpgradeable.sol
Original file line number Diff line number Diff line change
@@ -9,6 +9,9 @@ import { AccessControl } from "contracts/lib/AccessControl.sol";
import { IAccessControlled } from "contracts/interfaces/access-control/IAccessControlled.sol";
import { Errors } from "contracts/lib/Errors.sol";

/// @title Access Controlled Contract (upgradeable variant)
/// @notice This contract is to be inherited by any upgradeable protocol components that require
/// granular roles for execution, as defined by the Access Control Singleton contract.
abstract contract AccessControlledUpgradeable is UUPSUpgradeable, IAccessControlled {
using ERC165CheckerUpgradeable for address;

@@ -42,6 +45,7 @@ abstract contract AccessControlledUpgradeable is UUPSUpgradeable, IAccessControl
emit AccessControlUpdated(accessControl_);
}

/// @notice Gets the global Access Control Singleton configured for the protocol.
function getAccessControl() public view returns (address) {
AccessControlledStorage storage $ = _getAccessControlledUpgradeable();
return address($.accessControl);
@@ -71,6 +75,7 @@ abstract contract AccessControlledUpgradeable is UUPSUpgradeable, IAccessControl
return $.accessControl.hasRole(role_, account_);
}

/// @dev Helper function to get the EIP-7201 storage slot for the contract.
function _getAccessControlledUpgradeable()
private
pure
2 changes: 2 additions & 0 deletions contracts/interfaces/access-control/IAccessControlled.sol
Original file line number Diff line number Diff line change
@@ -4,6 +4,8 @@ pragma solidity ^0.8.19;
/// @title Access Controlled Interface
interface IAccessControlled {

/// @notice Emits when the global Access Control singleton contract is updated.
/// @param accessControl Address of the protocol-wide Access Control singleton contract.
event AccessControlUpdated(address indexed accessControl);

}
21 changes: 0 additions & 21 deletions contracts/interfaces/ip-org/IIPOrgFactory.sol

This file was deleted.

12 changes: 8 additions & 4 deletions contracts/ip-org/IPOrg.sol
Original file line number Diff line number Diff line change
@@ -13,8 +13,12 @@ import { IPAssetRegistry } from "contracts/IPAssetRegistry.sol";
import { ModuleRegistryKeys } from "contracts/lib/modules/ModuleRegistryKeys.sol";
import { Errors } from "contracts/lib/Errors.sol";

/// @notice IP Asset Organization
/// TODO(leeren): Deprecate upgradeability once the IPOrg contracts is finalized.
/// @title IP Organization Contract
/// @notice An IP Org represents a collection of IP Assets governed under a single
/// administrative entity. It serves both as an org-branded NFT wrapper of
/// the IP Asset group and as a conduit used by the IP registration module
/// for transferring IP ownership and configuring its IP-related metadata.
/// Crations of new IP Orgs happen through the IP Org Controller contract.
contract IPOrg is
IIPOrg,
ERC721Upgradeable
@@ -129,8 +133,8 @@ contract IPOrg is
_transfer(from_, to_, id_);
}

/// Returns the IP Org asset type for a given IP Org asset.
/// @dev reverts if id does not exist.
/// @notice Returns the IP Org asset type for a given IP Org asset.
/// @param id_ The identifier of the IP asset within the IP Org.
function ipOrgAssetType(uint256 id_) public view returns (uint8) {
if (!_exists(id_)) {
revert Errors.IPOrg_IdDoesNotExist();
7 changes: 3 additions & 4 deletions contracts/ip-org/IPOrgController.sol
Original file line number Diff line number Diff line change
@@ -17,17 +17,16 @@ import { IPOrg } from "contracts/ip-org/IPOrg.sol";
import { AccessControl } from "contracts/lib/AccessControl.sol";

/// @title IP Org Controller Contract
/// @custom:version 0.1.0
/// TODO(leeren): Deprecate upgradeability once IPOrg contracts are finalized.
/// @notice The IP Org Controller is the protocol-wide factory contract for creating
/// and tracking IP Orgs. On top of this, it acts as the ownership controller
/// for IP Orgs, allowing orgs to transfer ownership through a 2-step process.
contract IPOrgController is
UUPSUpgradeable,
AccessControlledUpgradeable,
IIPOrgController
{

/// @notice Tracks ownership and registration of IPOrgs.
/// TODO(leeren): Add tracking for allowlisted callers of each ipOrg.
/// TODO(leeren): Add deterministic identifiers for ipOrgs using CREATE2.
struct IPOrgRecord {
bool registered;
address owner;
5 changes: 4 additions & 1 deletion contracts/modules/registration/RegistrationModule.sol
Original file line number Diff line number Diff line change
@@ -17,7 +17,10 @@ import { IPAsset } from "contracts/lib/IPAsset.sol";


/// @title Registration Module
/// @notice Handles registration and transferring of IP assets..
/// @notice The registration module is responsible for registration, transferring, and
/// metadata management of IP assets. During registration, this module will
/// create register the IP asset in the global IP asset registry, and then
/// wrap it as an NFT under its governing IP Org.
contract RegistrationModule is BaseModule, IRegistrationModule, AccessControlled {

using Strings for uint256;

0 comments on commit 978580f

Please sign in to comment.