Skip to content
This repository has been archived by the owner on Apr 30, 2024. It is now read-only.

Commit

Permalink
refactor tests to multiple licenses
Browse files Browse the repository at this point in the history
  • Loading branch information
Raul committed Feb 1, 2024
1 parent df2d708 commit 4e168fe
Show file tree
Hide file tree
Showing 8 changed files with 185 additions and 146 deletions.
4 changes: 2 additions & 2 deletions contracts/interfaces/modules/IRegistrationModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ pragma solidity ^0.8.23;
interface IRegistrationModule {
event RootIPRegistered(address indexed caller, address indexed ipId, uint256 indexed policyId);

event DerivativeIPRegistered(address indexed caller, address indexed ipId, uint256 licenseId);
event DerivativeIPRegistered(address indexed caller, address indexed ipId, uint256[] licenseIds);

function registerRootIp(uint256 policyId, address tokenContract, uint256 tokenId) external returns (address);

function registerDerivativeIp(
uint256 licenseId,
uint256[] calldata licenseIds,
address tokenContract,
uint256 tokenId,
string memory ipName,
Expand Down
13 changes: 7 additions & 6 deletions contracts/interfaces/registries/ILicenseRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ interface ILicenseRegistry {
/// @notice Emitted when an IP is linked to its parent by burning a license
/// @param caller The address that called the function
/// @param ipId The id of the IP
/// @param parentIpId The id of the parent IP
event IpIdLinkedToParent(address indexed caller, address indexed ipId, address indexed parentIpId);
/// @param parentIpIds The ids of the parent IP
event IpIdLinkedToParents(address indexed caller, address indexed ipId, address[] indexed parentIpIds);

/// @notice Registers a policy framework manager into the contract, so it can add policy data for
/// licenses.
Expand Down Expand Up @@ -95,11 +95,12 @@ interface ILicenseRegistry {
address receiver
) external returns (uint256 licenseId);

/// @notice Links an IP to its parent IP, burning the license NFT and the policy allows it
/// @param licenseId The id of the license to burn
/// @param childIpId The id of the child IP
/// @notice Links an IP to the licensors (parent IP IDs) listed in the License NFTs, if their policies allow it,
/// burning the NFTs in the proccess. The caller must be the owner of the NFTs and the IP owner.
/// @param licenseIds The id of the licenses to burn
/// @param childIpId The id of the child IP to be linked
/// @param holder The address that holds the license
function linkIpToParent(uint256 licenseId, address childIpId, address holder) external;
function linkIpToParents(uint256[] calldata licenseIds, address childIpId, address holder) external;

///
/// Getters
Expand Down
11 changes: 5 additions & 6 deletions contracts/modules/RegistrationModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ contract RegistrationModule is BaseModule, IRegistrationModule {
return ipId;
}

/// @notice Registers an IP derivative into the protocol.
/// @param licenseId The license to incorporate for the new IP.
/// @notice Registers IP derivatives into the protocol.
/// @param licenseIds The licenses to incorporate for the new IP.
/// @param tokenContract The address of the NFT bound to the derivative IP.
/// @param tokenId The token id of the NFT bound to the derivative IP.
/// @param ipName The name assigned to the new IP.
Expand All @@ -77,7 +77,7 @@ contract RegistrationModule is BaseModule, IRegistrationModule {
/// TODO: Replace all metadata with a generic bytes parameter type, and do
/// encoding on the periphery contract level instead.
function registerDerivativeIp(
uint256 licenseId,
uint256[] calldata licenseIds,
address tokenContract,
uint256 tokenId,
string memory ipName,
Expand Down Expand Up @@ -115,10 +115,9 @@ contract RegistrationModule is BaseModule, IRegistrationModule {
// metadataProvider.setMetadata(ipId, metadata);

// Perform core IP derivative licensing - the license must be owned by the caller.
// TODO: return resulting policy index
LICENSE_REGISTRY.linkIpToParent(licenseId, ipId, msg.sender);
LICENSE_REGISTRY.linkIpToParents(licenseIds, ipId, msg.sender);

emit DerivativeIPRegistered(msg.sender, ipId, licenseId);
emit DerivativeIPRegistered(msg.sender, ipId, licenseIds);
}

/// @notice Gets the protocol-wide module identifier for this module.
Expand Down
103 changes: 49 additions & 54 deletions contracts/registries/LicenseRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,6 @@ contract LicenseRegistry is ERC1155, ILicenseRegistry {
/// This tracks the number of licenses registered in the protocol, it will not decrease when a license is burnt.
uint256 private _totalLicenses;

modifier onlyLicensee(uint256 licenseId, address holder) {
// Should ERC1155 operator count? IMO is a security risk. Better use ACL
if (balanceOf(holder, licenseId) == 0) {
revert Errors.LicenseRegistry__NotLicensee();
}
_;
}

constructor(address accessController, address ipAccountRegistry) ERC1155("") {
ACCESS_CONTROLLER = IAccessController(accessController);
IP_ACCOUNT_REGISTRY = IIPAccountRegistry(ipAccountRegistry);
Expand Down Expand Up @@ -106,7 +98,7 @@ contract LicenseRegistry is ERC1155, ILicenseRegistry {
if (!isPolicyDefined(polId)) {
revert Errors.LicenseRegistry__PolicyNotFound();
}
return _addPolictyIdToIp(ipId, polId, false);
return _addPolicyIdToIp(ipId, polId, false);
}

/// @notice Registers a policy into the contract. MUST be called by a registered
Expand Down Expand Up @@ -191,58 +183,61 @@ contract LicenseRegistry is ERC1155, ILicenseRegistry {
return licenseId;
}

/// Relates an IP ID with its parents (licensors), by burning the License NFT the holder owns
/// Licensing parameters related to linking IPAs must be verified in order to succeed, reverts otherwise.
/// The child IP ID will have the policy that the license represent added to it's own, if it's compatible with
/// existing child policies.
/// The child IP ID will be linked to the parent (if it wasn't before).
/// @param licenseId license NFT to be burned
/// @param childIpId that will receive the policy defined by licenseId
/// @param holder of the license NFT
function linkIpToParent(
uint256 licenseId,
/// @notice Links an IP to the licensors (parent IP IDs) listed in the License NFTs, if their policies allow it,
/// burning the NFTs in the proccess. The caller must be the owner of the NFTs and the IP owner.
/// @param licenseIds The id of the licenses to burn
/// @param childIpId The id of the child IP to be linked
/// @param holder The address that holds the license
function linkIpToParents(
uint256[] calldata licenseIds,
address childIpId,
address holder
) external onlyLicensee(licenseId, holder) {
) external {
// check the caller is owner or authorized by the childIp
if (
msg.sender != childIpId &&
!ACCESS_CONTROLLER.checkPermission(childIpId, msg.sender, address(this), this.linkIpToParent.selector)
!ACCESS_CONTROLLER.checkPermission(childIpId, msg.sender, address(this), this.linkIpToParents.selector)
) {
revert Errors.LicenseRegistry__UnauthorizedAccess();
}
// TODO: check if childIpId exists and is owned by holder
Licensing.License memory licenseData = _licenses[licenseId];
address parentIpId = licenseData.licensorIpId;
if (parentIpId == childIpId) {
revert Errors.LicenseRegistry__ParentIdEqualThanChild();
}
// TODO: check licensor exist
// TODO: check licensor not part of a branch tagged by disputer

// Verify linking params
Licensing.Policy memory pol = policy(licenseData.policyId);
if (ERC165Checker.supportsInterface(pol.policyFramework, type(ILinkParamVerifier).interfaceId)) {
if (
!ILinkParamVerifier(pol.policyFramework).verifyLink(
licenseId,
msg.sender,
childIpId,
parentIpId,
pol.data
)
) {
revert Errors.LicenseRegistry__LinkParentParamFailed();
uint256 licenses = licenseIds.length;
address[] memory licensors = new address[](licenses);
uint256[] memory values = new uint256[](licenses);
for (uint256 i = 0; i < licenses; i++) {
uint256 licenseId = licenseIds[i];
if (balanceOf(holder, licenseId) == 0) {
revert Errors.LicenseRegistry__NotLicensee();
}
Licensing.License memory licenseData = _licenses[licenseId];
licensors[i] = licenseData.licensorIpId;
// TODO: check licensor not part of a branch tagged by disputer
if (licensors[i] == childIpId) {
revert Errors.LicenseRegistry__ParentIdEqualThanChild();
}
// Verify linking params
Licensing.Policy memory pol = policy(licenseData.policyId);
if (ERC165Checker.supportsInterface(pol.policyFramework, type(ILinkParamVerifier).interfaceId)) {
if (
!ILinkParamVerifier(pol.policyFramework).verifyLink(
licenseId,
msg.sender,
childIpId,
licensors[i],
pol.data
)
) {
revert Errors.LicenseRegistry__LinkParentParamFailed();
}
}
// Add policy to kid
_addPolicyIdToIp(childIpId, licenseData.policyId, true);
// Set parent
_ipIdParents[childIpId].add(licensors[i]);
values[i] = 1;
}
// Add policy to kid
_addPolictyIdToIp(childIpId, licenseData.policyId, true);
// Set parent
_ipIdParents[childIpId].add(parentIpId);
emit IpIdLinkedToParent(msg.sender, childIpId, parentIpId);

// Burn license
_burn(holder, licenseId, 1);
emit IpIdLinkedToParents(msg.sender, childIpId, licensors);
// Burn licenses
_burnBatch(holder, licenseIds, values);
}

/// @notice True if the framework address is registered in LicenseRegistry
Expand Down Expand Up @@ -373,7 +368,7 @@ contract LicenseRegistry is ERC1155, ILicenseRegistry {
super._update(from, to, ids, values);
}

function _verifyRegisteredFramework(address policyFramework) internal view returns (address) {
function _verifyRegisteredFramework(address policyFramework) internal view {
if (!_registeredFrameworkManagers[policyFramework]) {
revert Errors.LicenseRegistry__FrameworkNotFound();
}
Expand All @@ -385,7 +380,7 @@ contract LicenseRegistry is ERC1155, ILicenseRegistry {
/// @param policyId id of the policy data
/// @param inheritedPolicy true if set in linkIpToParent, false otherwise
/// @return index of the policy added to the set
function _addPolictyIdToIp(address ipId, uint256 policyId, bool inheritedPolicy) internal returns (uint256 index) {
function _addPolicyIdToIp(address ipId, uint256 policyId, bool inheritedPolicy) internal returns (uint256 index) {
EnumerableSet.UintSet storage _pols = _policiesPerIpId[ipId];
if (!_pols.add(policyId)) {
revert Errors.LicenseRegistry__PolicyAlreadySetForIpId();
Expand Down Expand Up @@ -431,7 +426,7 @@ contract LicenseRegistry is ERC1155, ILicenseRegistry {
return (id, true);
}

function _verifyPolicy(Licensing.Policy memory pol) private view {
function _verifyPolicy(Licensing.Policy memory pol) private pure {
if (pol.policyFramework == address(0)) {
revert Errors.LicenseRegistry__PolicyNotFound();
}
Expand Down
8 changes: 5 additions & 3 deletions script/foundry/deployment/Main.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -340,9 +340,11 @@ contract Main is Script, BroadcastManager, JsonDeploymentHandler {
2,
deployer
);
uint256[] memory licenseIds = new uint256[](1);
licenseIds[0] = licenseId1;

registrationModule.registerDerivativeIp(
licenseId1,
licenseIds,
address(mockNft),
nftIds[3],
"best derivative ip",
Expand All @@ -353,8 +355,8 @@ contract Main is Script, BroadcastManager, JsonDeploymentHandler {
// /*///////////////////////////////////////////////////////////////
// LINK IPACCOUNTS TO PARENTS USING LICENSES
// ////////////////////////////////////////////////////////////////*/

licenseRegistry.linkIpToParent(licenseId1, getIpId(mockNft, nftIds[4]), deployer);
licenseRegistry.linkIpToParents(licenseIds, getIpId(mockNft, nftIds[4]), deployer);
}

function getIpId(MockERC721 mnft, uint256 tokenId) public view returns (address ipId) {
Expand Down
Loading

0 comments on commit 4e168fe

Please sign in to comment.