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

Fix Caller Parameter in PFM verify #119

Merged
merged 3 commits into from
Feb 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ interface IPolicyFrameworkManager is IERC165 {

/// @notice Verify policy parameters for minting a license.
/// @dev Enforced to be only callable by LicenseRegistry
/// @param caller the address executing the mint
/// @param licensee the address that holds the license and is executing the mint
/// @param mintingFromADerivative true if we verify minting a license from a derivative IP ID
/// @param receiver the address receiving the license
/// @param licensorIpId the IP id of the licensor
/// @param mintAmount the amount of licenses to mint
/// @param policyData the encoded framework policy data to verify
/// @return verified True if the link is verified
function verifyMint(
address caller,
address licensee,
bool mintingFromADerivative,
address licensorIpId,
address receiver,
Expand All @@ -56,14 +56,14 @@ interface IPolicyFrameworkManager is IERC165 {
/// @notice Verify policy parameters for linking a child IP to a parent IP (licensor) by burning a license NFT.
/// @dev Enforced to be only callable by LicenseRegistry
/// @param licenseId the license id to burn
/// @param caller the address executing the link
/// @param licensee the address that holds the license and is executing the link
/// @param ipId the IP id of the IP being linked
/// @param parentIpId the IP id of the parent IP
/// @param policyData the encoded framework policy data to verify
/// @return verified True if the link is verified
function verifyLink(
uint256 licenseId,
address caller,
address licensee,
address ipId,
address parentIpId,
bytes calldata policyData
Expand Down
12 changes: 7 additions & 5 deletions contracts/modules/licensing/LicensingModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,9 @@ contract LicensingModule is AccessControlled, ILicensingModule, BaseModule, Reen
}

// If a policy is set, then is only up to the policy params.
// Verify minting param
if (!pfm.verifyMint(msg.sender, isInherited, licensorIpId, receiver, amount, pol.frameworkData)) {
// When verifying mint via PFM, pass in `receiver` as the `licensee` since the receiver is the one who will own
LeoHChen marked this conversation as resolved.
Show resolved Hide resolved
// the license NFT after minting.
if (!pfm.verifyMint(receiver, isInherited, licensorIpId, receiver, amount, pol.frameworkData)) {
revert Errors.LicensingModule__MintLicenseParamFailed();
}

Expand Down Expand Up @@ -298,7 +299,7 @@ contract LicensingModule is AccessControlled, ILicensingModule, BaseModule, Reen
revert Errors.LicensingModule__IncompatibleLicensorCommercialPolicy();
}

_linkIpToParent(i, licenseId, licenseData.policyId, pol, licenseData.licensorIpId, childIpId);
_linkIpToParent(i, licenseId, licenseData.policyId, pol, licenseData.licensorIpId, childIpId, holder);
return (licenseData.licensorIpId, pol.royaltyPolicy, pol.royaltyData);
}

Expand Down Expand Up @@ -485,7 +486,8 @@ contract LicensingModule is AccessControlled, ILicensingModule, BaseModule, Reen
uint256 policyId,
Licensing.Policy memory pol,
address licensor,
address childIpId
address childIpId,
address licensee
) private {
// TODO: check licensor not part of a branch tagged by disputer
if (licensor == childIpId) {
Expand All @@ -495,7 +497,7 @@ contract LicensingModule is AccessControlled, ILicensingModule, BaseModule, Reen
if (
!IPolicyFrameworkManager(pol.policyFramework).verifyLink(
licenseId,
msg.sender,
licensee,
childIpId,
licensor,
pol.frameworkData
Expand Down
12 changes: 6 additions & 6 deletions contracts/modules/licensing/PILPolicyFrameworkManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,14 @@ contract PILPolicyFrameworkManager is
/// @notice Verify policy parameters for linking a child IP to a parent IP (licensor) by burning a license NFT.
/// @dev Enforced to be only callable by LicenseRegistry
/// @param licenseId the license id to burn
/// @param caller the address executing the link
/// @param licensee the address that holds the license and is executing the linking
/// @param ipId the IP id of the IP being linked
/// @param parentIpId the IP id of the parent IP
/// @param policyData the encoded framework policy data to verify
/// @return verified True if the link is verified
function verifyLink(
uint256 licenseId,
address caller,
address licensee,
address ipId,
address parentIpId,
bytes calldata policyData
Expand All @@ -104,7 +104,7 @@ contract PILPolicyFrameworkManager is
if (policy.commercializerChecker != address(0)) {
// No need to check if the commercializerChecker supports the IHookModule interface, as it was checked
// when the policy was registered.
if (!IHookModule(policy.commercializerChecker).verify(caller, policy.commercializerCheckerData)) {
if (!IHookModule(policy.commercializerChecker).verify(licensee, policy.commercializerCheckerData)) {
return false;
}
}
Expand All @@ -113,15 +113,15 @@ contract PILPolicyFrameworkManager is

/// @notice Verify policy parameters for minting a license.
/// @dev Enforced to be only callable by LicenseRegistry
/// @param caller the address executing the mint
/// @param licensee the address that holds the license and is executing the mint
/// @param mintingFromADerivative true if the license is minting from a derivative IPA
/// @param licensorIpId the IP id of the licensor
/// @param receiver the address receiving the license
/// @param mintAmount the amount of licenses to mint
/// @param policyData the encoded framework policy data to verify
/// @return verified True if the link is verified
function verifyMint(
address caller,
address licensee,
bool mintingFromADerivative,
address licensorIpId,
address receiver,
Expand All @@ -138,7 +138,7 @@ contract PILPolicyFrameworkManager is
if (policy.commercializerChecker != address(0)) {
// No need to check if the commercializerChecker supports the IHookModule interface, as it was checked
// when the policy was registered.
if (!IHookModule(policy.commercializerChecker).verify(caller, policy.commercializerCheckerData)) {
if (!IHookModule(policy.commercializerChecker).verify(licensee, policy.commercializerCheckerData)) {
return false;
}
}
Expand Down
58 changes: 48 additions & 10 deletions test/foundry/integration/big-bang/SingleNftCollection.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,16 @@ import { IRoyaltyPolicyLAP } from "../../../../contracts/interfaces/modules/roya

// test
import { BaseIntegration } from "../BaseIntegration.t.sol";
import { MockTokenGatedHook } from "../../mocks/MockTokenGatedHook.sol";
import { MockERC721 } from "../../mocks/token/MockERC721.sol";

contract BigBang_Integration_SingleNftCollection is BaseIntegration {
using EnumerableSet for EnumerableSet.UintSet;

MockTokenGatedHook internal mockTokenGatedHook;

MockERC721 internal mockGatedNft;

mapping(uint256 tokenId => address ipAccount) internal ipAcct;

mapping(string name => uint256 licenseId) internal licenseIds;
Expand All @@ -28,6 +34,9 @@ contract BigBang_Integration_SingleNftCollection is BaseIntegration {
function setUp() public override {
super.setUp();

mockTokenGatedHook = new MockTokenGatedHook();
mockGatedNft = new MockERC721("MockGatedNft");

// Add PIL PFM policies

_setPILPolicyFrameworkManager();
Expand All @@ -42,8 +51,8 @@ contract BigBang_Integration_SingleNftCollection is BaseIntegration {
attribution: false,
commercialUse: true,
commercialAttribution: true,
commercializerChecker: address(0),
commercializerCheckerData: "",
commercializerChecker: address(mockTokenGatedHook),
commercializerCheckerData: abi.encode(address(mockGatedNft)),
commercialRevShare: derivCheapFlexibleRevShare,
derivativesAllowed: true,
derivativesAttribution: true,
Expand Down Expand Up @@ -148,6 +157,10 @@ contract BigBang_Integration_SingleNftCollection is BaseIntegration {
vm.startPrank(u.carl);
mockNFT.mintId(u.carl, 6);

// Carl needs to hold an NFT from mockGatedNFT collection to mint license pil_com_deriv_cheap_flexible
// (verified by the mockTokenGatedHook commercializer checker)
mockGatedNft.mint(u.carl);

mockToken.approve(address(royaltyPolicyLAP), 100 ether);

uint256[] memory carl_license_from_root_alice = new uint256[](1);
Expand Down Expand Up @@ -180,7 +193,11 @@ contract BigBang_Integration_SingleNftCollection is BaseIntegration {
// Carl activates one of the two licenses on his NFT 7 IPAccount, linking as child to Bob's NFT 3 IPAccount
{
vm.startPrank(u.carl);
mockNFT.mintId(u.carl, 7);
mockNFT.mintId(u.carl, 7); // NFT for Carl's IPAccount7

// Carl is minting license on non-commercial policy, so no commercializer checker is involved.
// Thus, no need to mint anything (although Carl already has mockGatedNft from above)

uint256[] memory carl_license_from_root_bob = new uint256[](1);
carl_license_from_root_bob[0] = licensingModule.mintLicense(
policyIds["pil_noncom_deriv_reciprocal_derivative"],
Expand All @@ -190,19 +207,36 @@ contract BigBang_Integration_SingleNftCollection is BaseIntegration {
emptyRoyaltyPolicyLAPInitParams
);

IRoyaltyPolicyLAP.InitParams memory params = IRoyaltyPolicyLAP.InitParams({
IRoyaltyPolicyLAP.InitParams memory royaltyContextRegister = IRoyaltyPolicyLAP.InitParams({
targetAncestors: new address[](1),
targetRoyaltyAmount: new uint32[](1),
parentAncestors1: new address[](0),
parentAncestors2: new address[](0),
parentAncestorsRoyalties1: new uint32[](0),
parentAncestorsRoyalties2: new uint32[](0)
});
params.targetAncestors[0] = ipAcct[3];
params.targetRoyaltyAmount[0] = 0;

ipAcct[7] = registerIpAccount(mockNFT, 7, u.carl);
linkIpToParents(carl_license_from_root_bob, ipAcct[7], u.carl, abi.encode(params));
royaltyContextRegister.targetAncestors[0] = ipAcct[3];
royaltyContextRegister.targetRoyaltyAmount[0] = 0;

// TODO: events check
ipAssetRegistry.register(
carl_license_from_root_bob,
abi.encode(royaltyContextRegister),
block.chainid,
address(mockNFT),
7,
address(ipResolver),
true,
abi.encode(
IP.MetadataV1({
name: "IP NAME",
hash: bytes32("hash"),
registrationDate: uint64(block.timestamp),
registrant: u.carl, // caller
uri: "external URL"
})
)
);
}

// Alice mints 2 license for policy "pil_com_deriv_cheap_flexible" on Bob's NFT 3 IPAccount
Expand All @@ -216,6 +250,10 @@ contract BigBang_Integration_SingleNftCollection is BaseIntegration {

mockToken.approve(address(royaltyPolicyLAP), mintAmount * 100 ether);

// Alice needs to hold an NFT from mockGatedNFT collection to mint license on pil_com_deriv_cheap_flexible
// (verified by the mockTokenGatedHook commercializer checker)
mockGatedNft.mint(u.alice);

uint256[] memory alice_license_from_root_bob = new uint256[](1);
alice_license_from_root_bob[0] = licensingModule.mintLicense(
policyIds["pil_com_deriv_cheap_flexible"],
Expand Down Expand Up @@ -285,7 +323,7 @@ contract BigBang_Integration_SingleNftCollection is BaseIntegration {
});

uint256[] memory carl_licenses = new uint256[](2);
// Commercial license
// Commercial license (Carl already has mockGatedNft from above, so he passes commercializer checker check)
carl_licenses[0] = licensingModule.mintLicense(
policyIds["pil_com_deriv_cheap_flexible"], // ipAcct[1] has this policy attached
ipAcct[1],
Expand Down
7 changes: 7 additions & 0 deletions test/foundry/utils/BaseTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,13 @@ contract BaseTest is Test, DeployHelper, LicensingHelper {
// NOTE: accessController is IAccessController, which doesn't expose `initialize` function.
AccessController(address(accessController)).initialize(address(ipAccountRegistry), getModuleRegistry());

accessController.setGlobalPermission(
address(ipAssetRegistry),
address(licensingModule),
bytes4(licensingModule.linkIpToParents.selector),
AccessPermission.ALLOW
);

// If REAL Registration Module and Licensing Module are deployed, set global permissions
if (deployConditions.module.registrationModule && deployConditions.module.licensingModule) {
accessController.setGlobalPermission(
Expand Down
Loading