License Config / Hook

An optional hook that can be attached to an entire IP Asset or specific license for dynamic minting fees.

🗒️

Contract

View the smart contract here.

Optionally, you can attach a LicensingConfig to a license which contains a mintingFee and a licensingHook, as shown below. The hook contained in the config will be run before a user mints a License Token, meaning you can insert logic to be run upon minting a license.

/// @notice This struct is used by IP owners to define the configuration
/// when others are minting license tokens of their IP through the LicensingModule.
/// When the `mintLicenseTokens` function of LicensingModule is called, the LicensingModule will read
/// this configuration to determine the minting fee and execute the licensing hook if set.
/// IP owners can set these configurations for each License or set the configuration for the IP
/// so that the configuration applies to all licenses of the IP.
/// If both the license and IP have the configuration, then the license configuration takes precedence.
/// @param isSet Whether the configuration is set or not.
/// @param mintingFee The minting fee to be paid when minting license tokens.
/// @param licensingHook  The hook contract address for the licensing module, or address(0) if none
/// @param hookData The data to be used by the licensing hook.
struct LicensingConfig {
  bool isSet;
  uint256 mintingFee;
  address licensingHook;
  bytes hookData;
}

You can also attach the LicensingConfig to an IP as a whole, so it will execute on every license that belongs to the IP. Note that if both an IP-wide config and license-specific config are set, the license-specific config will take priority.

The hook itself is defined below. You can see it contains information about the license, who is minting the License Token, and who is receiving it. You can view the contract here.

Logic that is Possible with License Config

  1. Max Number of Licenses: The licensingHook (described in the next section) is where you can define logic for the max number of licenses that can be minted. For example, reverting the transaction if the max number of licenses has already been minted.
  2. Disallowing Derivatives: If you register a derivative of an IP Asset, that derivative cannot change its License Terms as described here. You can be wondering: "What if I, as a derivative, want to disallow derivatives of myself, but my License Terms allow derivatives and I cannot change this?" To solve this, you can simply add a licensingHook (described in the next section) to your IP Asset that aborts every time it is called, so derivatives cannot be made.
  3. Minting Fee: Similar to #2 above... what about the minting fee? Although you cannot change License Terms on a derivative IP Asset (and thus the mintingFee inside of it), you can change the minting fee for that derivative by modifying the mintingFee in the License Config, or returning a totalMintingFee from the licensingHook (described in the next section).
  4. Dynamic Pricing for Minting a License Token: Set dynamic pricing for minting a License Token from an IP Asset based on how many total have been minted, how many licenses the user is minting, or even who the user is. All of this data is available in the licensingHook (described in the next section).

Licensing Hook

The beforeMintLicenseTokens function, also called the licensingHook, is a function that can be called before a License Token is minted to determine the final totalMintingFee of that License Token. The owner of an IP Asset must set the License Config, with their own implementation of the beforeMintLicenseTokens function, for this to be called.

It can also be used to implement various checks and logic, as outlined above.

🚧

Warning!

Beware of potentially malicious implementations of external license hooks. Please first verify the code of the hook you choose because it may be not reviewed or audited by the Story team.

/// @notice This function is called when the LicensingModule mints license tokens.
/// @dev The hook can be used to implement various checks and determine the minting price.
/// The hook should revert if the minting is not allowed.
/// @param caller The address of the caller who calling the mintLicenseTokens() function.
/// @param licensorIpId The ID of licensor IP from which issue the license tokens.
/// @param licenseTemplate The address of the license template.
/// @param licenseTermsId The ID of the license terms within the license template,
/// which is used to mint license tokens.
/// @param amount The amount of license tokens to mint.
/// @param receiver The address of the receiver who receive the license tokens.
/// @param hookData The data to be used by the licensing hook.
/// @return totalMintingFee The total minting fee to be paid when minting amount of license tokens.
function beforeMintLicenseTokens(
  address caller,
  address licensorIpId,
  address licenseTemplate,
  uint256 licenseTermsId,
  uint256 amount,
  address receiver,
  bytes calldata hookData
) external returns (uint256 totalMintingFee);

Note that it returns the totalMintingFee. You may be wondering, "I can set the minting fee in the License Terms, in the LicenseConfig, and return a dynamic price from beforeMintLicenseTokens. What will the final minting fee actually be?" Here is the priority:

Minting FeeImportance
The totalMintingFee returned from beforeMintLicenseTokensHighest Priority
The mintingFee set in the LicenseConfig⬇️
The mintingFee set in the License TermsLowest Priority