Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Latest 25 from a total of 551 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
Amount
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Register Policy | 8495095 | 220 days ago | IN | 0 ETH | 0.00007679 | ||||
| Register Policy | 8495067 | 220 days ago | IN | 0 ETH | 0.00007678 | ||||
| Register Policy | 8494969 | 220 days ago | IN | 0 ETH | 0.00007677 | ||||
| Register Policy | 7497810 | 363 days ago | IN | 0 ETH | 0.00898244 | ||||
| Register Policy | 6594703 | 502 days ago | IN | 0 ETH | 0.04111921 | ||||
| Register Policy | 6388234 | 534 days ago | IN | 0 ETH | 0.00081615 | ||||
| Register Policy | 6324753 | 545 days ago | IN | 0 ETH | 0.00001714 | ||||
| Register Policy | 6323477 | 545 days ago | IN | 0 ETH | 0.00133223 | ||||
| Register Policy | 6323445 | 545 days ago | IN | 0 ETH | 0.00189487 | ||||
| Register Policy | 6316578 | 547 days ago | IN | 0 ETH | 0.00026619 | ||||
| Register Policy | 6316212 | 547 days ago | IN | 0 ETH | 0.03986283 | ||||
| Register Policy | 6316187 | 547 days ago | IN | 0 ETH | 0.03642553 | ||||
| Register Policy | 6316042 | 547 days ago | IN | 0 ETH | 0.00318999 | ||||
| Register Policy | 6315981 | 547 days ago | IN | 0 ETH | 0.0048554 | ||||
| Register Policy | 6305283 | 548 days ago | IN | 0 ETH | 0.00032043 | ||||
| Register Policy | 6304201 | 549 days ago | IN | 0 ETH | 0.00127851 | ||||
| Register Policy | 6052243 | 586 days ago | IN | 0 ETH | 0.00499192 | ||||
| Register Policy | 6015191 | 591 days ago | IN | 0 ETH | 0.00031063 | ||||
| Register Policy | 6015152 | 591 days ago | IN | 0 ETH | 0.00027809 | ||||
| Register Policy | 6015035 | 591 days ago | IN | 0 ETH | 0.00023583 | ||||
| Register Policy | 6014960 | 591 days ago | IN | 0 ETH | 0.00025405 | ||||
| Register Policy | 6014933 | 591 days ago | IN | 0 ETH | 0.00025145 | ||||
| Register Policy | 6014931 | 591 days ago | IN | 0 ETH | 0.00021994 | ||||
| Register Policy | 6014843 | 591 days ago | IN | 0 ETH | 0.00033265 | ||||
| Register Policy | 6014699 | 591 days ago | IN | 0 ETH | 0.00059127 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
PILPolicyFrameworkManager
Compiler Version
v0.8.23+commit.f704f362
Optimization Enabled:
Yes with 20000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
// external
import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";
import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";
import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
// contracts
import { IHookModule } from "../../interfaces/modules/base/IHookModule.sol";
import { ILicensingModule } from "../../interfaces/modules/licensing/ILicensingModule.sol";
import { Licensing } from "../../lib/Licensing.sol";
import { Errors } from "../../lib/Errors.sol";
import { PILFrameworkErrors } from "../../lib/PILFrameworkErrors.sol";
// solhint-disable-next-line max-line-length
import { IPILPolicyFrameworkManager, PILPolicy, PILAggregator, RegisterPILPolicyParams } from "../../interfaces/modules/licensing/IPILPolicyFrameworkManager.sol";
import { BasePolicyFrameworkManager } from "../../modules/licensing/BasePolicyFrameworkManager.sol";
import { LicensorApprovalChecker } from "../../modules/licensing/parameter-helpers/LicensorApprovalChecker.sol";
/// @title PILPolicyFrameworkManager
/// @notice PIL Policy Framework Manager implements the PIL Policy Framework logic for encoding and decoding PIL
/// policies into the LicenseRegistry and verifying the licensing parameters for linking, minting, and transferring.
contract PILPolicyFrameworkManager is
IPILPolicyFrameworkManager,
BasePolicyFrameworkManager,
LicensorApprovalChecker,
ReentrancyGuard
{
using ERC165Checker for address;
using Strings for *;
/// @dev Hash of an empty string array
bytes32 private constant _EMPTY_STRING_ARRAY_HASH =
0x569e75fc77c1a856f6daaf9e69d8a9566ca34aa47f9133711ce065a571af0cfd;
constructor(
address accessController,
address ipAccountRegistry,
address licensing,
string memory name_,
string memory licenseUrl_
)
BasePolicyFrameworkManager(licensing, name_, licenseUrl_)
LicensorApprovalChecker(
accessController,
ipAccountRegistry,
address(ILicensingModule(licensing).LICENSE_REGISTRY())
)
{}
/// @notice Registers a new policy to the registry
/// @dev Internally, this function must generate a Licensing.Policy struct and call registerPolicy.
/// @param params parameters needed to register a PILPolicy
/// @return policyId The ID of the newly registered policy
function registerPolicy(RegisterPILPolicyParams calldata params) external nonReentrant returns (uint256 policyId) {
/// Minting fee amount & address checked in LicensingModule, no need to check here.
/// We don't limit charging for minting to commercial use, you could sell a NC license in theory.
_verifyComercialUse(params.policy, params.royaltyPolicy, params.mintingFee, params.mintingFeeToken);
_verifyDerivatives(params.policy);
/// TODO: DO NOT deploy on production networks without hashing string[] values instead of storing them
Licensing.Policy memory pol = Licensing.Policy({
isLicenseTransferable: params.transferable,
policyFramework: address(this),
frameworkData: abi.encode(params.policy),
royaltyPolicy: params.royaltyPolicy,
royaltyData: abi.encode(params.policy.commercialRevShare),
mintingFee: params.mintingFee,
mintingFeeToken: params.mintingFeeToken
});
// No need to emit here, as the LicensingModule will emit the event
return LICENSING_MODULE.registerPolicy(pol);
}
/// @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 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 licensee,
address ipId,
address parentIpId,
bytes calldata policyData
) external override nonReentrant onlyLicensingModule returns (bool) {
PILPolicy memory policy = abi.decode(policyData, (PILPolicy));
// Trying to burn a license to create a derivative, when the license doesn't allow derivatives.
if (!policy.derivativesAllowed) {
return false;
}
// If the policy defines the licensor must approve derivatives, check if the
// derivative is approved by the licensor
if (policy.derivativesApproval && !isDerivativeApproved(licenseId, ipId)) {
return false;
}
// Check if the commercializerChecker allows the link
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(licensee, policy.commercializerCheckerData)) {
return false;
}
}
return true;
}
/// @notice Verify policy parameters for minting a license.
/// @dev Enforced to be only callable by LicenseRegistry
/// @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 licensee,
bool mintingFromADerivative,
address licensorIpId,
address receiver,
uint256 mintAmount,
bytes memory policyData
) external nonReentrant onlyLicensingModule returns (bool) {
PILPolicy memory policy = abi.decode(policyData, (PILPolicy));
// If the policy defines no reciprocal derivatives are allowed (no derivatives of derivatives),
// and we are mintingFromADerivative we don't allow minting
if (!policy.derivativesReciprocal && mintingFromADerivative) {
return false;
}
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(licensee, policy.commercializerCheckerData)) {
return false;
}
}
return true;
}
/// @notice Returns the aggregation data for inherited policies of an IP asset.
/// @param ipId The ID of the IP asset to get the aggregator for
/// @return rights The PILAggregator struct
function getAggregator(address ipId) external view returns (PILAggregator memory rights) {
bytes memory policyAggregatorData = LICENSING_MODULE.policyAggregatorData(address(this), ipId);
if (policyAggregatorData.length == 0) {
revert PILFrameworkErrors.PILPolicyFrameworkManager__RightsNotFound();
}
rights = abi.decode(policyAggregatorData, (PILAggregator));
}
/// @notice gets the PILPolicy for a given policy ID decoded from Licensing.Policy.frameworkData
/// @dev Do not call this function from a smart contract, it is only for off-chain
/// @param policyId The ID of the policy to get
/// @return policy The PILPolicy struct
function getPILPolicy(uint256 policyId) external view returns (PILPolicy memory policy) {
Licensing.Policy memory pol = LICENSING_MODULE.policy(policyId);
return abi.decode(pol.frameworkData, (PILPolicy));
}
/// @notice Verify compatibility of one or more policies when inheriting them from one or more parent IPs.
/// @dev Enforced to be only callable by LicenseRegistry
/// @dev The assumption in this method is that we can add parents later on, hence the need
/// for an aggregator, if not we will do this when linking to parents directly with an
/// array of policies.
/// @param aggregator common state of the policies for the IP
/// @param policyId the ID of the policy being inherited
/// @param policy the policy to inherit
/// @return changedAgg true if the aggregator was changed
/// @return newAggregator the new aggregator
// solhint-disable-next-line code-complexity
function processInheritedPolicies(
bytes memory aggregator,
uint256 policyId,
bytes memory policy
) external view onlyLicensingModule returns (bool changedAgg, bytes memory newAggregator) {
PILAggregator memory agg;
PILPolicy memory newPolicy = abi.decode(policy, (PILPolicy));
if (aggregator.length == 0) {
// Initialize the aggregator
agg = PILAggregator({
commercial: newPolicy.commercialUse,
derivativesReciprocal: newPolicy.derivativesReciprocal,
lastPolicyId: policyId,
territoriesAcc: keccak256(abi.encode(newPolicy.territories)),
distributionChannelsAcc: keccak256(abi.encode(newPolicy.distributionChannels)),
contentRestrictionsAcc: keccak256(abi.encode(newPolicy.contentRestrictions))
});
return (true, abi.encode(agg));
} else {
agg = abi.decode(aggregator, (PILAggregator));
// Either all are reciprocal or none are
if (agg.derivativesReciprocal != newPolicy.derivativesReciprocal) {
revert PILFrameworkErrors.PILPolicyFrameworkManager__ReciprocalValueMismatch();
} else if (agg.derivativesReciprocal && newPolicy.derivativesReciprocal) {
// Ids are uniqued because we hash them to compare on creation in LicenseRegistry,
// so we can compare the ids safely.
if (agg.lastPolicyId != policyId) {
revert PILFrameworkErrors.PILPolicyFrameworkManager__ReciprocalButDifferentPolicyIds();
}
} else {
// Both non reciprocal
if (agg.commercial != newPolicy.commercialUse) {
revert PILFrameworkErrors.PILPolicyFrameworkManager__CommercialValueMismatch();
}
bytes32 newHash = _verifHashedParams(
agg.territoriesAcc,
keccak256(abi.encode(newPolicy.territories)),
_EMPTY_STRING_ARRAY_HASH
);
if (newHash != agg.territoriesAcc) {
agg.territoriesAcc = newHash;
changedAgg = true;
}
newHash = _verifHashedParams(
agg.distributionChannelsAcc,
keccak256(abi.encode(newPolicy.distributionChannels)),
_EMPTY_STRING_ARRAY_HASH
);
if (newHash != agg.distributionChannelsAcc) {
agg.distributionChannelsAcc = newHash;
changedAgg = true;
}
newHash = _verifHashedParams(
agg.contentRestrictionsAcc,
keccak256(abi.encode(newPolicy.contentRestrictions)),
_EMPTY_STRING_ARRAY_HASH
);
if (newHash != agg.contentRestrictionsAcc) {
agg.contentRestrictionsAcc = newHash;
changedAgg = true;
}
}
}
return (changedAgg, abi.encode(agg));
}
/// @notice Returns the stringified JSON policy data for the LicenseRegistry.uri(uint256) method.
/// @dev Must return ERC1155 OpenSea standard compliant metadata.
/// @param policyData The encoded licensing policy data to be decoded by the PFM
/// @return jsonString The OpenSea-compliant metadata URI of the policy
function policyToJson(bytes memory policyData) public pure returns (string memory) {
PILPolicy memory policy = abi.decode(policyData, (PILPolicy));
/* solhint-disable */
// Follows the OpenSea standard for JSON metadata.
// **Attributions**
string memory json = string(
abi.encodePacked(
'{"trait_type": "Attribution", "value": "',
policy.attribution ? "true" : "false",
'"},',
// Skip transferable, it's already added in the common attributes by the LicenseRegistry.
// Should be managed by the LicenseRegistry, not the PFM.
_policyCommercialTraitsToJson(policy),
_policyDerivativeTraitsToJson(policy)
)
);
json = string(abi.encodePacked(json, '{"trait_type": "Territories", "value": ['));
uint256 count = policy.territories.length;
for (uint256 i = 0; i < count; ++i) {
json = string(abi.encodePacked(json, '"', policy.territories[i], '"'));
if (i != count - 1) {
// skip comma for last element in the array
json = string(abi.encodePacked(json, ","));
}
}
json = string(abi.encodePacked(json, "]},")); // close the trait_type: "Territories" array
json = string(abi.encodePacked(json, '{"trait_type": "Distribution Channels", "value": ['));
count = policy.distributionChannels.length;
for (uint256 i = 0; i < count; ++i) {
json = string(abi.encodePacked(json, '"', policy.distributionChannels[i], '"'));
if (i != count - 1) {
// skip comma for last element in the array
json = string(abi.encodePacked(json, ","));
}
}
json = string(abi.encodePacked(json, "]},")); // close the trait_type: "Distribution Channels" array
// NOTE: (above) last trait added by PFM should have a comma at the end.
/* solhint-enable */
return json;
}
/// @dev Encodes the commercial traits of PIL policy into a JSON string for OpenSea
/// @param policy The policy to encode
function _policyCommercialTraitsToJson(PILPolicy memory policy) internal pure returns (string memory) {
/* solhint-disable */
// NOTE: TOTAL_RNFT_SUPPLY = 1000 in trait with max_value. For numbers, don't add any display_type, so that
// they will show up in the "Ranking" section of the OpenSea UI.
return
string(
abi.encodePacked(
'{"trait_type": "Commercial Use", "value": "',
policy.commercialUse ? "true" : "false",
'"},',
'{"trait_type": "Commercial Attribution", "value": "',
policy.commercialAttribution ? "true" : "false",
'"},',
'{"trait_type": "Commercial Revenue Share", "max_value": 1000, "value": ',
policy.commercialRevShare.toString(),
"},",
'{"trait_type": "Commercializer Check", "value": "',
policy.commercializerChecker.toHexString(),
// Skip on commercializerCheckerData as it's bytes as irrelevant for the user metadata
'"},'
)
);
/* solhint-enable */
}
/// @dev Encodes the derivative traits of PIL policy into a JSON string for OpenSea
/// @param policy The policy to encode
function _policyDerivativeTraitsToJson(PILPolicy memory policy) internal pure returns (string memory) {
/* solhint-disable */
// NOTE: TOTAL_RNFT_SUPPLY = 1000 in trait with max_value. For numbers, don't add any display_type, so that
// they will show up in the "Ranking" section of the OpenSea UI.
return
string(
abi.encodePacked(
'{"trait_type": "Derivatives Allowed", "value": "',
policy.derivativesAllowed ? "true" : "false",
'"},',
'{"trait_type": "Derivatives Attribution", "value": "',
policy.derivativesAttribution ? "true" : "false",
'"},',
'{"trait_type": "Derivatives Approval", "value": "',
policy.derivativesApproval ? "true" : "false",
'"},',
'{"trait_type": "Derivatives Reciprocal", "value": "',
policy.derivativesReciprocal ? "true" : "false",
'"},'
)
);
/* solhint-enable */
}
/// @dev Checks the configuration of commercial use and throws if the policy is not compliant
/// @param policy The policy to verify
/// @param royaltyPolicy The address of the royalty policy
// solhint-disable-next-line code-complexity
function _verifyComercialUse(
PILPolicy calldata policy,
address royaltyPolicy,
uint256 mintingFee,
address mintingFeeToken
) internal view {
if (!policy.commercialUse) {
if (policy.commercialAttribution) {
revert PILFrameworkErrors.PILPolicyFrameworkManager__CommercialDisabled_CantAddAttribution();
}
if (policy.commercializerChecker != address(0)) {
revert PILFrameworkErrors.PILPolicyFrameworkManager__CommercialDisabled_CantAddCommercializers();
}
if (policy.commercialRevShare > 0) {
revert PILFrameworkErrors.PILPolicyFrameworkManager__CommercialDisabled_CantAddRevShare();
}
if (royaltyPolicy != address(0)) {
revert PILFrameworkErrors.PILPolicyFrameworkManager__CommercialDisabled_CantAddRoyaltyPolicy();
}
if (mintingFee > 0) {
revert PILFrameworkErrors.PILPolicyFrameworkManager__CommercialDisabled_CantAddMintingFee();
}
if (mintingFeeToken != address(0)) {
revert PILFrameworkErrors.PILPolicyFrameworkManager__CommercialDisabled_CantAddMintingFeeToken();
}
} else {
if (royaltyPolicy == address(0)) {
revert PILFrameworkErrors.PILPolicyFrameworkManager__CommercialEnabled_RoyaltyPolicyRequired();
}
if (policy.commercializerChecker != address(0)) {
if (!policy.commercializerChecker.supportsInterface(type(IHookModule).interfaceId)) {
revert Errors.PolicyFrameworkManager__CommercializerCheckerDoesNotSupportHook(
policy.commercializerChecker
);
}
IHookModule(policy.commercializerChecker).validateConfig(policy.commercializerCheckerData);
}
}
}
/// @notice Checks the configuration of derivative parameters and throws if the policy is not compliant
/// @param policy The policy to verify
function _verifyDerivatives(PILPolicy calldata policy) internal pure {
if (!policy.derivativesAllowed) {
if (policy.derivativesAttribution) {
revert PILFrameworkErrors.PILPolicyFrameworkManager__DerivativesDisabled_CantAddAttribution();
}
if (policy.derivativesApproval) {
revert PILFrameworkErrors.PILPolicyFrameworkManager__DerivativesDisabled_CantAddApproval();
}
if (policy.derivativesReciprocal) {
revert PILFrameworkErrors.PILPolicyFrameworkManager__DerivativesDisabled_CantAddReciprocal();
}
}
}
/// @dev Verifies compatibility for params where the valid options are either permissive value, or equal params
/// @param oldHash hash of the old param
/// @param newHash hash of the new param
/// @param permissive hash of the most permissive param
/// @return result the hash that's different from the permissive hash
function _verifHashedParams(
bytes32 oldHash,
bytes32 newHash,
bytes32 permissive
) internal pure returns (bytes32 result) {
if (oldHash == newHash) {
return newHash;
}
if (oldHash != permissive && newHash != permissive) {
revert PILFrameworkErrors.PILPolicyFrameworkManager__StringArrayMismatch();
}
if (oldHash != permissive) {
return oldHash;
}
if (newHash != permissive) {
return newHash;
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol)
pragma solidity ^0.8.20;
import {Math} from "./math/Math.sol";
import {SignedMath} from "./math/SignedMath.sol";
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant HEX_DIGITS = "0123456789abcdef";
uint8 private constant ADDRESS_LENGTH = 20;
/**
* @dev The `value` string doesn't fit in the specified `length`.
*/
error StringsInsufficientHexLength(uint256 value, uint256 length);
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/
function toStringSigned(int256 value) internal pure returns (string memory) {
return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value)));
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
uint256 localValue = value;
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = HEX_DIGITS[localValue & 0xf];
localValue >>= 4;
}
if (localValue != 0) {
revert StringsInsufficientHexLength(value, length);
}
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal
* representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);
}
/**
* @dev Returns true if the two strings are equal.
*/
function equal(string memory a, string memory b) internal pure returns (bool) {
return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165Checker.sol)
pragma solidity ^0.8.20;
import {IERC165} from "./IERC165.sol";
/**
* @dev Library used to query support of an interface declared via {IERC165}.
*
* Note that these functions return the actual result of the query: they do not
* `revert` if an interface is not supported. It is up to the caller to decide
* what to do in these cases.
*/
library ERC165Checker {
// As per the EIP-165 spec, no interface should ever match 0xffffffff
bytes4 private constant INTERFACE_ID_INVALID = 0xffffffff;
/**
* @dev Returns true if `account` supports the {IERC165} interface.
*/
function supportsERC165(address account) internal view returns (bool) {
// Any contract that implements ERC165 must explicitly indicate support of
// InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid
return
supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) &&
!supportsERC165InterfaceUnchecked(account, INTERFACE_ID_INVALID);
}
/**
* @dev Returns true if `account` supports the interface defined by
* `interfaceId`. Support for {IERC165} itself is queried automatically.
*
* See {IERC165-supportsInterface}.
*/
function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {
// query support of both ERC165 as per the spec and support of _interfaceId
return supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId);
}
/**
* @dev Returns a boolean array where each value corresponds to the
* interfaces passed in and whether they're supported or not. This allows
* you to batch check interfaces for a contract where your expectation
* is that some interfaces may not be supported.
*
* See {IERC165-supportsInterface}.
*/
function getSupportedInterfaces(
address account,
bytes4[] memory interfaceIds
) internal view returns (bool[] memory) {
// an array of booleans corresponding to interfaceIds and whether they're supported or not
bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);
// query support of ERC165 itself
if (supportsERC165(account)) {
// query support of each interface in interfaceIds
for (uint256 i = 0; i < interfaceIds.length; i++) {
interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]);
}
}
return interfaceIdsSupported;
}
/**
* @dev Returns true if `account` supports all the interfaces defined in
* `interfaceIds`. Support for {IERC165} itself is queried automatically.
*
* Batch-querying can lead to gas savings by skipping repeated checks for
* {IERC165} support.
*
* See {IERC165-supportsInterface}.
*/
function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {
// query support of ERC165 itself
if (!supportsERC165(account)) {
return false;
}
// query support of each interface in interfaceIds
for (uint256 i = 0; i < interfaceIds.length; i++) {
if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) {
return false;
}
}
// all interfaces supported
return true;
}
/**
* @notice Query if a contract implements an interface, does not check ERC165 support
* @param account The address of the contract to query for support of an interface
* @param interfaceId The interface identifier, as specified in ERC-165
* @return true if the contract at account indicates support of the interface with
* identifier interfaceId, false otherwise
* @dev Assumes that account contains a contract that supports ERC165, otherwise
* the behavior of this method is undefined. This precondition can be checked
* with {supportsERC165}.
*
* Some precompiled contracts will falsely indicate support for a given interface, so caution
* should be exercised when using this function.
*
* Interface identification is specified in ERC-165.
*/
function supportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internal view returns (bool) {
// prepare call
bytes memory encodedParams = abi.encodeCall(IERC165.supportsInterface, (interfaceId));
// perform static call
bool success;
uint256 returnSize;
uint256 returnValue;
assembly {
success := staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)
returnSize := returndatasize()
returnValue := mload(0x00)
}
return success && returnSize >= 0x20 && returnValue > 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol)
pragma solidity ^0.8.20;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant NOT_ENTERED = 1;
uint256 private constant ENTERED = 2;
uint256 private _status;
/**
* @dev Unauthorized reentrant call.
*/
error ReentrancyGuardReentrantCall();
constructor() {
_status = NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be NOT_ENTERED
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
// Any calls to nonReentrant after this point will fail
_status = ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == ENTERED;
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
import { IModule } from "./IModule.sol";
/// @notice Hook Module Interface
interface IHookModule is IModule {
/// @notice Verify if the caller can pass the hook
/// @param caller The address of the caller
/// @param data The arbitrary data to be verified
/// @return bool Whether or not the caller has passed the hook's verification
function verify(address caller, bytes calldata data) external returns (bool);
/// @notice Validates the configuration for the hook.
/// @param configData The configuration data for the hook.
function validateConfig(bytes calldata configData) external view;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
import { Licensing } from "../../../lib/Licensing.sol";
import { IModule } from "../base/IModule.sol";
import { RoyaltyModule } from "../../../modules/royalty/RoyaltyModule.sol";
import { ILicenseRegistry } from "../../registries/ILicenseRegistry.sol";
import { IDisputeModule } from "../dispute/IDisputeModule.sol";
/// @title ILicensingModule
interface ILicensingModule is IModule {
/// @notice Status of a policy on IP asset
/// @param index The local index of the policy in the IP asset
/// @param isSet True if the policy is set in the IP asset
/// @param active True if the policy is active
/// @param isInherited True if the policy is inherited from a parent IP asset
struct PolicySetup {
uint256 index;
bool isSet;
bool active;
bool isInherited;
}
/// @notice Emitted when a policy framework is created by registering a policy framework manager
/// @param framework The address of the IPolicyFrameworkManager
/// @param framework The policy framework data
event PolicyFrameworkRegistered(address indexed framework, string name, string licenseTextUrl);
/// @notice Emitted when a policy is added to the contract
/// @param policyId The id of the policy
/// @param policyFrameworkManager The address of the policy framework manager
/// @param frameworkData The policy framework specific encoded data
/// @param royaltyPolicy The address of the royalty policy
/// @param royaltyData The royalty policy specific encoded data
/// @param mintingFee The fee to be paid when minting a license
/// @param mintingFeeToken The token to be used to pay the minting fee
event PolicyRegistered(
uint256 indexed policyId,
address indexed policyFrameworkManager,
bytes frameworkData,
address royaltyPolicy,
bytes royaltyData,
uint256 mintingFee,
address mintingFeeToken
);
/// @notice Emitted when a policy is added to an IP
/// @param caller The address that called the function
/// @param ipId The id of the IP
/// @param policyId The id of the policy
/// @param index The index of the policy in the IP's policy set
/// @param isInherited Whether the policy was inherited from a parent IP (linking) or set by IP owner
event PolicyAddedToIpId(
address indexed caller,
address indexed ipId,
uint256 indexed policyId,
uint256 index,
bool isInherited
);
/// @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 parentIpIds The ids of the parent IPs
event IpIdLinkedToParents(address indexed caller, address indexed ipId, address[] parentIpIds);
/// @notice Returns the canonical protocol-wide RoyaltyModule
function ROYALTY_MODULE() external view returns (RoyaltyModule);
/// @notice Returns the canonical protocol-wide LicenseRegistry
function LICENSE_REGISTRY() external view returns (ILicenseRegistry);
/// @notice Returns the canonical protocol-wide DisputeModule
function DISPUTE_MODULE() external view returns (IDisputeModule);
/// @notice Registers a policy framework manager into the contract, so it can add policy data for licenses.
/// @param manager the address of the manager. Will be ERC165 checked for IPolicyFrameworkManager
function registerPolicyFrameworkManager(address manager) external;
/// @notice Registers a policy into the contract. MUST be called by a registered
/// framework or it will revert. The policy data and its integrity must be
/// verified by the policy framework manager.
/// @param pol The Licensing policy data. MUST have same policy framework as the caller address
/// @return policyId The id of the newly registered policy
function registerPolicy(Licensing.Policy memory pol) external returns (uint256 policyId);
/// @notice Adds a policy to the set of policies of an IP
/// @param ipId The id of the IP
/// @param polId The id of the policy
/// @return indexOnIpId The index of the policy in the IP's policy set
function addPolicyToIp(address ipId, uint256 polId) external returns (uint256 indexOnIpId);
/// @notice Mints a license to create derivative IP. License NFTs represent a policy granted by IPs (licensors).
/// Reverts if caller is not authorized by any of the licensors.
/// @dev This NFT needs to be burned in order to link a derivative IP with its parents. If this is the first
/// combination of policy and licensors, a new licenseId will be created (by incrementing prev totalLicenses).
/// If not, the license is fungible and an id will be reused. The licensing terms that regulate creating new
/// licenses will be verified to allow minting.
/// @param policyId The id of the policy with the licensing parameters
/// @param licensorIpId The id of the licensor IP
/// @param amount The amount of licenses to mint
/// @param receiver The address that will receive the license
/// @param royaltyContext The context for the royalty module to process
/// @return licenseId The ID of the license NFT(s)
function mintLicense(
uint256 policyId,
address licensorIpId,
uint256 amount,
address receiver,
bytes calldata royaltyContext
) external returns (uint256 licenseId);
/// @notice Links an IP to the licensors listed in the license NFTs, if their policies allow it. Burns the license
/// NFTs in the proccess. The caller must be the owner of the IP asset and license NFTs.
/// @param licenseIds The id of the licenses to burn
/// @param childIpId The id of the child IP to be linked
/// @param royaltyContext The context for the royalty module to process
function linkIpToParents(uint256[] calldata licenseIds, address childIpId, bytes calldata royaltyContext) external;
///
/// Getters
///
/// @notice Returns if the framework address is registered in the LicensingModule.
/// @param policyFramework The address of the policy framework manager
/// @return isRegistered True if the framework is registered
function isFrameworkRegistered(address policyFramework) external view returns (bool);
/// @notice Returns amount of distinct licensing policies in the LicensingModule.
/// @return totalPolicies The amount of policies
function totalPolicies() external view returns (uint256);
/// @notice Returns the policy data for policyId, reverts if not found.
/// @param policyId The id of the policy
/// @return pol The policy data
function policy(uint256 policyId) external view returns (Licensing.Policy memory pol);
/// @notice Returns the policy id for the given policy data, or 0 if not found.
/// @param pol The policy data in Policy struct
/// @return policyId The id of the policy
function getPolicyId(Licensing.Policy calldata pol) external view returns (uint256 policyId);
/// @notice Returns the policy aggregator data for the given IP ID in the framework.
/// @param framework The address of the policy framework manager
/// @param ipId The id of the IP asset
/// @return data The encoded policy aggregator data to be decoded by the framework manager
function policyAggregatorData(address framework, address ipId) external view returns (bytes memory);
/// @notice Returns if policyId exists in the LicensingModule
/// @param policyId The id of the policy
/// @return isDefined True if the policy is defined
function isPolicyDefined(uint256 policyId) external view returns (bool);
/// @notice Returns the policy ids attached to an IP
/// @dev Potentially gas-intensive operation, use with care.
/// @param isInherited True if the policy is inherited from a parent IP
/// @param ipId The id of the IP asset
/// @return policyIds The ids of policy ids for the IP
function policyIdsForIp(bool isInherited, address ipId) external view returns (uint256[] memory policyIds);
/// @notice Returns the total number of policies attached to an IP
/// @param isInherited True if the policy is inherited from a parent IP
/// @param ipId The id of the IP asset
/// @return totalPolicies The total number of policies for the IP
function totalPoliciesForIp(bool isInherited, address ipId) external view returns (uint256);
/// @notice Returns if a given policyId is attached to an IP
/// @param isInherited True if the policy is inherited from a parent IP
/// @param ipId The id of the IP asset
/// @param policyId The id of the policy
/// @return isSet True if the policy is set in the IP asset
function isPolicyIdSetForIp(bool isInherited, address ipId, uint256 policyId) external view returns (bool);
/// @notice Returns the policy ID for an IP by local index on the IP's policy set
/// @param isInherited True if the policy is inherited from a parent IP
/// @param ipId The id of the IP asset to check
/// @param index The local index of a policy in the IP's policy set
/// @return policyId The id of the policy
function policyIdForIpAtIndex(
bool isInherited,
address ipId,
uint256 index
) external view returns (uint256 policyId);
/// @notice Returns the policy data for an IP by the policy's local index on the IP's policy set
/// @param isInherited True if the policy is inherited from a parent IP
/// @param ipId The id of the IP asset to check
/// @param index The local index of a policy in the IP's policy set
/// @return policy The policy data
function policyForIpAtIndex(
bool isInherited,
address ipId,
uint256 index
) external view returns (Licensing.Policy memory);
/// @notice Returns the status of a policy in an IP's policy set
/// @param ipId The id of the IP asset to check
/// @param policyId The id of the policy
/// @return index The local index of the policy in the IP's policy set
/// @return isInherited True if the policy is inherited from a parent IP
/// @return active True if the policy is active
function policyStatus(
address ipId,
uint256 policyId
) external view returns (uint256 index, bool isInherited, bool active);
/// @notice Returns if the given policy attached to the given IP is inherited from a parent IP.
/// @param ipId The id of the IP asset that has the policy attached
/// @param policyId The id of the policy to check if inherited
/// @return isInherited True if the policy is inherited from a parent IP
function isPolicyInherited(address ipId, uint256 policyId) external view returns (bool);
/// @notice Returns if an IP is a derivative of another IP
/// @param parentIpId The id of the parent IP asset to check
/// @param childIpId The id of the child IP asset to check
/// @return isParent True if the child IP is a derivative of the parent IP
function isParent(address parentIpId, address childIpId) external view returns (bool);
/// @notice Returns the list of parent IP assets for a given child IP asset
/// @param ipId The id of the child IP asset to check
/// @return parentIpIds The ids of the parent IP assets
function parentIpIds(address ipId) external view returns (address[] memory);
/// @notice Returns the total number of parents for an IP asset
/// @param ipId The id of the IP asset to check
/// @return totalParents The total number of parent IP assets
function totalParentsForIpId(address ipId) external view returns (uint256);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
/// @title Licensing
/// @notice Types and constants used by the licensing related contracts
library Licensing {
/// @notice A particular configuration (flavor) of a Policy Framework, setting values for the licensing
/// terms (parameters) of the framework.
/// @param isLicenseTransferable Whether or not the license is transferable
/// @param policyFramework address of the IPolicyFrameworkManager this policy is based on
/// @param frameworkData Data to be used by the policy framework to verify minting and linking
/// @param royaltyPolicy address of the royalty policy to be used by the policy framework, if any
/// @param royaltyData Data to be used by the royalty policy (for example, encoding of the royalty percentage)
/// @param mintingFee Fee to be paid when minting a license
/// @param mintingFeeToken Token to be used to pay the minting fee
struct Policy {
bool isLicenseTransferable;
address policyFramework;
bytes frameworkData;
address royaltyPolicy;
bytes royaltyData;
uint256 mintingFee;
address mintingFeeToken;
}
/// @notice Data that define a License Agreement NFT
/// @param policyId Id of the policy this license is based on, which will be set in the derivative IP when the
/// license is burnt for linking
/// @param licensorIpId Id of the IP this license is for
/// @param transferable Whether or not the license is transferable
struct License {
uint256 policyId;
address licensorIpId;
bool transferable;
// TODO: support for transfer hooks
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
/// @title Errors Library
/// @notice Library for all Story Protocol contract errors.
library Errors {
////////////////////////////////////////////////////////////////////////////
// Governance //
////////////////////////////////////////////////////////////////////////////
error Governance__OnlyProtocolAdmin();
error Governance__ZeroAddress();
error Governance__ProtocolPaused();
error Governance__InconsistentState();
error Governance__NewStateIsTheSameWithOldState();
error Governance__UnsupportedInterface(string interfaceName);
////////////////////////////////////////////////////////////////////////////
// IPAccount //
////////////////////////////////////////////////////////////////////////////
error IPAccount__InvalidSigner();
error IPAccount__InvalidSignature();
error IPAccount__ExpiredSignature();
error IPAccount__InvalidCalldata();
error IPAccount__InvalidAccessController();
////////////////////////////////////////////////////////////////////////////
// Module //
////////////////////////////////////////////////////////////////////////////
/// @notice The caller is not allowed to call the provided module.
error Module_Unauthorized();
////////////////////////////////////////////////////////////////////////////
// IPAccountRegistry //
////////////////////////////////////////////////////////////////////////////
error IPAccountRegistry_InvalidIpAccountImpl();
////////////////////////////////////////////////////////////////////////////
// IPAssetRegistry //
////////////////////////////////////////////////////////////////////////////
/// @notice The IP asset has already been registered.
error IPAssetRegistry__AlreadyRegistered();
/// @notice The IP account has already been created.
error IPAssetRegistry__IPAccountAlreadyCreated();
/// @notice The IP asset has not yet been registered.
error IPAssetRegistry__NotYetRegistered();
/// @notice The IP asset registrant is not authorized.
error IPAssetRegistry__RegistrantUnauthorized();
/// @notice The specified IP resolver is not valid.
error IPAssetRegistry__ResolverInvalid();
/// @notice Caller not authorized to perform the IP registry function call.
error IPAssetRegistry__Unauthorized();
/// @notice The deployed address of account doesn't match with IP ID.
error IPAssetRegistry__InvalidAccount();
/// @notice The metadata provider is not valid.
error IPAssetRegistry__InvalidMetadataProvider();
////////////////////////////////////////////////////////////////////////////
// IPResolver ///
////////////////////////////////////////////////////////////////////////////
/// @notice The targeted IP does not yet have an IP account.
error IPResolver_InvalidIP();
/// @notice Caller not authorized to perform the IP resolver function call.
error IPResolver_Unauthorized();
////////////////////////////////////////////////////////////////////////////
// Metadata Provider ///
////////////////////////////////////////////////////////////////////////////
/// @notice Provided hash metadata is not valid.
error MetadataProvider__HashInvalid();
/// @notice The caller is not the authorized IP asset owner.
error MetadataProvider__IPAssetOwnerInvalid();
/// @notice Provided hash metadata is not valid.
error MetadataProvider__NameInvalid();
/// @notice The new metadata provider is not compatible with the old provider.
error MetadataProvider__MetadataNotCompatible();
/// @notice Provided registrant metadata is not valid.
error MetadataProvider__RegistrantInvalid();
/// @notice Provided registration date is not valid.
error MetadataProvider__RegistrationDateInvalid();
/// @notice Caller does not access to set metadata storage for the provider.
error MetadataProvider__Unauthorized();
/// @notice A metadata provider upgrade is not currently available.
error MetadataProvider__UpgradeUnavailable();
/// @notice The upgrade provider is not valid.
error MetadataProvider__UpgradeProviderInvalid();
/// @notice Provided metadata URI is not valid.
error MetadataProvider__URIInvalid();
////////////////////////////////////////////////////////////////////////////
// LicenseRegistry //
////////////////////////////////////////////////////////////////////////////
error LicenseRegistry__CallerNotLicensingModule();
error LicenseRegistry__ZeroLicensingModule();
error LicensingModule__CallerNotLicenseRegistry();
error LicenseRegistry__RevokedLicense();
/// @notice emitted when trying to transfer a license that is not transferable (by policy)
error LicenseRegistry__NotTransferable();
/// @notice emitted on constructor if dispute module is not set
error LicenseRegistry__ZeroDisputeModule();
////////////////////////////////////////////////////////////////////////////
// LicensingModule //
////////////////////////////////////////////////////////////////////////////
error LicensingModule__PolicyAlreadySetForIpId();
error LicensingModule__FrameworkNotFound();
error LicensingModule__EmptyLicenseUrl();
error LicensingModule__InvalidPolicyFramework();
error LicensingModule__ParamVerifierLengthMismatch();
error LicensingModule__PolicyNotFound();
error LicensingModule__NotLicensee();
error LicensingModule__ParentIdEqualThanChild();
error LicensingModule__LicensorDoesntHaveThisPolicy();
error LicensingModule__MintLicenseParamFailed();
error LicensingModule__LinkParentParamFailed();
error LicensingModule__TransferParamFailed();
error LicensingModule__InvalidLicensor();
error LicensingModule__ParamVerifierAlreadySet();
error LicensingModule__CommercialTermInNonCommercialPolicy();
error LicensingModule__EmptyParamName();
error LicensingModule__UnregisteredFrameworkAddingPolicy();
error LicensingModule__UnauthorizedAccess();
error LicensingModule__LicensorNotRegistered();
error LicensingModule__CallerNotLicensorAndPolicyNotSet();
error LicensingModule__DerivativesCannotAddPolicy();
error LicensingModule__IncompatibleRoyaltyPolicyAddress();
error LicensingModule__IncompatibleRoyaltyPolicyDerivativeRevShare();
error LicensingModule__IncompatibleLicensorCommercialPolicy();
error LicensingModule__IncompatibleLicensorRoyaltyDerivativeRevShare();
error LicensingModule__DerivativeRevShareSumExceedsMaxRNFTSupply();
error LicensingModule__MismatchBetweenRoyaltyPolicy();
error LicensingModule__RegisterPolicyFrameworkMismatch();
error LicensingModule__RoyaltyPolicyNotWhitelisted();
error LicensingModule__MintingFeeTokenNotWhitelisted();
error LicensingModule__ReceiverZeroAddress();
error LicensingModule__MintAmountZero();
/// @notice emitted when trying to interact with an IP that has been disputed in the DisputeModule
error LicensingModule__DisputedIpId();
/// @notice emitted when linking a license from a licensor that has been disputed in the DisputeModule
error LicensingModule__LinkingRevokedLicense();
////////////////////////////////////////////////////////////////////////////
// LicensingModuleAware //
////////////////////////////////////////////////////////////////////////////
error LicensingModuleAware__CallerNotLicensingModule();
////////////////////////////////////////////////////////////////////////////
// PolicyFrameworkManager //
////////////////////////////////////////////////////////////////////////////
error PolicyFrameworkManager__GettingPolicyWrongFramework();
error PolicyFrameworkManager__CommercializerCheckerDoesNotSupportHook(address commercializer);
////////////////////////////////////////////////////////////////////////////
// LicensorApprovalChecker //
////////////////////////////////////////////////////////////////////////////
error LicensorApprovalChecker__Unauthorized();
////////////////////////////////////////////////////////////////////////////
// Dispute Module //
////////////////////////////////////////////////////////////////////////////
error DisputeModule__ZeroArbitrationPolicy();
error DisputeModule__ZeroArbitrationRelayer();
error DisputeModule__ZeroDisputeTag();
error DisputeModule__ZeroLinkToDisputeEvidence();
error DisputeModule__NotWhitelistedArbitrationPolicy();
error DisputeModule__NotWhitelistedDisputeTag();
error DisputeModule__NotWhitelistedArbitrationRelayer();
error DisputeModule__NotDisputeInitiator();
error DisputeModule__NotInDisputeState();
error DisputeModule__NotAbleToResolve();
error DisputeModule__NotRegisteredIpId();
error DisputeModule__UnauthorizedAccess();
error ArbitrationPolicySP__ZeroDisputeModule();
error ArbitrationPolicySP__ZeroPaymentToken();
error ArbitrationPolicySP__NotDisputeModule();
////////////////////////////////////////////////////////////////////////////
// Royalty Module //
////////////////////////////////////////////////////////////////////////////
error RoyaltyModule__ZeroRoyaltyPolicy();
error RoyaltyModule__NotWhitelistedRoyaltyPolicy();
error RoyaltyModule__ZeroRoyaltyToken();
error RoyaltyModule__NotWhitelistedRoyaltyToken();
error RoyaltyModule__NoRoyaltyPolicySet();
error RoyaltyModule__IncompatibleRoyaltyPolicy();
error RoyaltyModule__NotAllowedCaller();
error RoyaltyModule__ZeroLicensingModule();
error RoyaltyModule__CanOnlyMintSelectedPolicy();
error RoyaltyModule__NoParentsOnLinking();
error RoyaltyModule__NotRegisteredIpId();
error RoyaltyPolicyLAP__ZeroRoyaltyModule();
error RoyaltyPolicyLAP__ZeroLiquidSplitFactory();
error RoyaltyPolicyLAP__ZeroLiquidSplitMain();
error RoyaltyPolicyLAP__NotRoyaltyModule();
error RoyaltyPolicyLAP__ZeroLicensingModule();
error RoyaltyPolicyLAP__AboveParentLimit();
error RoyaltyPolicyLAP__AboveAncestorsLimit();
error RoyaltyPolicyLAP__AboveRoyaltyStackLimit();
error RoyaltyPolicyLAP__InvalidAncestorsLength();
error RoyaltyPolicyLAP__InvalidAncestors();
error RoyaltyPolicyLAP__InvalidRoyaltyAmountLength();
error RoyaltyPolicyLAP__InvalidAncestorsHash();
error RoyaltyPolicyLAP__InvalidParentRoyaltiesLength();
error RoyaltyPolicyLAP__InvalidAncestorsRoyalty();
error RoyaltyPolicyLAP__ImplementationAlreadySet();
error RoyaltyPolicyLAP__ZeroAncestorsVaultImpl();
error RoyaltyPolicyLAP__NotFullOwnership();
error RoyaltyPolicyLAP__UnlinkableToParents();
error RoyaltyPolicyLAP__TransferFailed();
error RoyaltyPolicyLAP__LastPositionNotAbleToMintLicense();
error AncestorsVaultLAP__ZeroRoyaltyPolicyLAP();
error AncestorsVaultLAP__AlreadyClaimed();
error AncestorsVaultLAP__InvalidAncestorsHash();
error AncestorsVaultLAP__InvalidClaimer();
error AncestorsVaultLAP__ClaimerNotAnAncestor();
error AncestorsVaultLAP__ETHBalanceNotZero();
error AncestorsVaultLAP__ERC20BalanceNotZero();
error AncestorsVaultLAP__TransferFailed();
////////////////////////////////////////////////////////////////////////////
// ModuleRegistry //
////////////////////////////////////////////////////////////////////////////
error ModuleRegistry__ModuleAddressZeroAddress();
error ModuleRegistry__ModuleAddressNotContract();
error ModuleRegistry__ModuleAlreadyRegistered();
error ModuleRegistry__NameEmptyString();
error ModuleRegistry__NameAlreadyRegistered();
error ModuleRegistry__NameDoesNotMatch();
error ModuleRegistry__ModuleNotRegistered();
error ModuleRegistry__InterfaceIdZero();
error ModuleRegistry__ModuleTypeAlreadyRegistered();
error ModuleRegistry__ModuleTypeNotRegistered();
error ModuleRegistry__ModuleNotSupportExpectedModuleTypeInterfaceId();
error ModuleRegistry__ModuleTypeEmptyString();
////////////////////////////////////////////////////////////////////////////
// RegistrationModule //
////////////////////////////////////////////////////////////////////////////
/// @notice The caller is not the owner of the root IP NFT.
error RegistrationModule__InvalidOwner();
////////////////////////////////////////////////////////////////////////////
// AccessController //
////////////////////////////////////////////////////////////////////////////
error AccessController__IPAccountIsZeroAddress();
error AccessController__IPAccountIsNotValid(address ipAccount);
error AccessController__SignerIsZeroAddress();
error AccessController__CallerIsNotIPAccount();
error AccessController__PermissionIsNotValid();
error AccessController__BothCallerAndRecipientAreNotRegisteredModule(address signer, address to);
error AccessController__PermissionDenied(address ipAccount, address signer, address to, bytes4 func);
////////////////////////////////////////////////////////////////////////////
// AccessControlled //
////////////////////////////////////////////////////////////////////////////
error AccessControlled__ZeroAddress();
error AccessControlled__NotIpAccount(address ipAccount);
error AccessControlled__CallerIsNotIpAccount(address caller);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
/// @title PILFrameworkErrors Errors Library
/// @notice Library for all PILFramework related contract errors.
library PILFrameworkErrors {
////////////////////////////////////////////////////////////////////////////
// PILPolicyFrameworkManager //
////////////////////////////////////////////////////////////////////////////
error PILPolicyFrameworkManager__CommercialDisabled_CantAddAttribution();
error PILPolicyFrameworkManager__CommercialDisabled_CantAddCommercializers();
error PILPolicyFrameworkManager__CommercialDisabled_CantAddRevShare();
error PILPolicyFrameworkManager__DerivativesDisabled_CantAddAttribution();
error PILPolicyFrameworkManager__DerivativesDisabled_CantAddApproval();
error PILPolicyFrameworkManager__DerivativesDisabled_CantAddReciprocal();
error PILPolicyFrameworkManager__RightsNotFound();
error PILPolicyFrameworkManager__CommercialDisabled_CantAddRoyaltyPolicy();
error PILPolicyFrameworkManager__CommercialEnabled_RoyaltyPolicyRequired();
error PILPolicyFrameworkManager__ReciprocalButDifferentPolicyIds();
error PILPolicyFrameworkManager__ReciprocalValueMismatch();
error PILPolicyFrameworkManager__CommercialValueMismatch();
error PILPolicyFrameworkManager__StringArrayMismatch();
error PILPolicyFrameworkManager__CommercialDisabled_CantAddMintingFee();
error PILPolicyFrameworkManager__CommercialDisabled_CantAddMintingFeeToken();
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
import { IPolicyFrameworkManager } from "../../../interfaces/modules/licensing/IPolicyFrameworkManager.sol";
/// @notice Licensing parameters for the Programmable IP License v1 (PIL) standard
/// @param transferable Whether or not the license is transferable
/// @param attribution Whether or not attribution is required when reproducing the work
/// @param commercialUse Whether or not the work can be used commercially
/// @param commercialAttribution Whether or not attribution is required when reproducing the work commercially
/// @param commercializerChecker commercializers that are allowed to commercially exploit the work. If zero address,
/// then no restrictions is enforced.
/// @param commercialRevShare Percentage of revenue that must be shared with the licensor
/// @param derivativesAllowed Whether or not the licensee can create derivatives of his work
/// @param derivativesAttribution Whether or not attribution is required for derivatives of the work
/// @param derivativesApproval Whether or not the licensor must approve derivatives of the work before they can be
/// linked to the licensor IP ID
/// @param derivativesReciprocal Whether or not the licensee must license derivatives of the work under the same terms.
/// @param territories List of territories where the license is valid. If empty, global.
/// @param distributionChannels List of distribution channels where the license is valid. Empty if no restrictions.
/// @param contentRestrictions List of content restrictions. Empty if no restrictions.
/// TODO: DO NOT deploy on production networks without hashing string[] instead of storing them
struct PILPolicy {
bool attribution;
bool commercialUse;
bool commercialAttribution;
address commercializerChecker;
bytes commercializerCheckerData;
uint32 commercialRevShare;
bool derivativesAllowed;
bool derivativesAttribution;
bool derivativesApproval;
bool derivativesReciprocal;
string[] territories;
string[] distributionChannels;
string[] contentRestrictions;
}
/// @param transferable Whether or not the license is transferable
/// @param royaltyPolicy Address of a royalty policy contract (e.g. RoyaltyPolicyLS) that will handle royalty payments
/// @param mintingFee Fee to be paid when minting a license
/// @param mintingFeeToken Token to be used to pay the minting fee
/// @param policy PILPolicy compliant licensing term values
struct RegisterPILPolicyParams {
bool transferable;
address royaltyPolicy;
uint256 mintingFee;
address mintingFeeToken;
PILPolicy policy;
}
/// @notice Struct that accumulates values of inherited policies so we can verify compatibility when inheriting
/// new policies.
/// @dev The assumption is that new policies may be added later, not only when linking an IP to its parent.
/// @param commercial Whether or not there is a policy that allows commercial use
/// @param derivativesReciprocal Whether or not there is a policy that requires derivatives to be licensed under the
/// same terms
/// @param lastPolicyId The last policy ID that was added to the IP
/// @param territoriesAcc The last hash of the territories array
/// @param distributionChannelsAcc The last hash of the distributionChannels array
/// @param contentRestrictionsAcc The last hash of the contentRestrictions array
struct PILAggregator {
bool commercial;
bool derivativesReciprocal;
uint256 lastPolicyId;
bytes32 territoriesAcc;
bytes32 distributionChannelsAcc;
bytes32 contentRestrictionsAcc;
}
/// @title IPILPolicyFrameworkManager
/// @notice Defines the interface for a Policy Framework Manager compliant with the PIL standard
interface IPILPolicyFrameworkManager is IPolicyFrameworkManager {
/// @notice Registers a new policy to the registry
/// @dev Internally, this function must generate a Licensing.Policy struct and call registerPolicy.
/// @param params parameters needed to register a PILPolicy
/// @return policyId The ID of the newly registered policy
function registerPolicy(RegisterPILPolicyParams calldata params) external returns (uint256 policyId);
/// @notice Returns the aggregation data for inherited policies of an IP asset.
/// @param ipId The ID of the IP asset to get the aggregator for
/// @return rights The PILAggregator struct
function getAggregator(address ipId) external view returns (PILAggregator memory rights);
/// @notice gets the PILPolicy for a given policy ID decoded from Licensing.Policy.frameworkData
/// @dev Do not call this function from a smart contract, it is only for off-chain
/// @param policyId The ID of the policy to get
/// @return policy The PILPolicy struct
function getPILPolicy(uint256 policyId) external view returns (PILPolicy memory policy);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
// external
import { ERC165 } from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
// contracts
import { IPolicyFrameworkManager } from "../../interfaces/modules/licensing/IPolicyFrameworkManager.sol";
import { LicensingModuleAware } from "../../modules/licensing/LicensingModuleAware.sol";
/// @title BasePolicyFrameworkManager
/// @notice Base contract for policy framework managers.
abstract contract BasePolicyFrameworkManager is IPolicyFrameworkManager, ERC165, LicensingModuleAware {
/// @notice Returns the name to be show in license NFT (LNFT) metadata
string public override name;
/// @notice Returns the URL to the off chain legal agreement template text
string public override licenseTextUrl;
constructor(address licensing, string memory name_, string memory licenseTextUrl_) LicensingModuleAware(licensing) {
name = name_;
licenseTextUrl = licenseTextUrl_;
}
/// @notice IERC165 interface support.
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return interfaceId == type(IPolicyFrameworkManager).interfaceId || super.supportsInterface(interfaceId);
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
import { AccessControlled } from "../../../access/AccessControlled.sol";
import { ILicenseRegistry } from "../../../interfaces/registries/ILicenseRegistry.sol";
/// @title LicensorApprovalChecker
/// @notice Manages the approval of derivative IP accounts by the licensor. Used to verify
/// licensing terms like "Derivatives With Approval" in PIL.
abstract contract LicensorApprovalChecker is AccessControlled {
/// @notice Emits when a derivative IP account is approved by the licensor.
/// @param licenseId The ID of the license waiting for approval
/// @param ipId The ID of the derivative IP to be approved
/// @param caller The executor of the approval
/// @param approved Result of the approval
event DerivativeApproved(uint256 indexed licenseId, address indexed ipId, address indexed caller, bool approved);
/// @notice Returns the license registry address
ILicenseRegistry public immutable LICENSE_REGISTRY;
/// @notice Approvals for derivative IP.
/// @dev License Id => licensor => childIpId => approved
mapping(uint256 => mapping(address => mapping(address => bool))) private _approvals;
constructor(
address accessController,
address ipAccountRegistry,
address licenseRegistry
) AccessControlled(accessController, ipAccountRegistry) {
LICENSE_REGISTRY = ILicenseRegistry(licenseRegistry);
}
/// @notice Approves or disapproves a derivative IP account.
/// @param licenseId The ID of the license waiting for approval
/// @param childIpId The ID of the derivative IP to be approved
/// @param approved Result of the approval
function setApproval(uint256 licenseId, address childIpId, bool approved) external {
address licensorIpId = LICENSE_REGISTRY.licensorIpId(licenseId);
_setApproval(licensorIpId, licenseId, childIpId, approved);
}
/// @notice Checks if a derivative IP account is approved by the licensor.
/// @param licenseId The ID of the license NFT issued from a policy of the licensor
/// @param childIpId The ID of the derivative IP to be approved
/// @return approved True if the derivative IP account using the license is approved
function isDerivativeApproved(uint256 licenseId, address childIpId) public view returns (bool) {
address licensorIpId = LICENSE_REGISTRY.licensorIpId(licenseId);
return _approvals[licenseId][licensorIpId][childIpId];
}
/// @notice Sets the approval for a derivative IP account.
/// @dev This function is only callable by the licensor IP account.
/// @param licensorIpId The ID of the licensor IP account
/// @param licenseId The ID of the license waiting for approval
/// @param childIpId The ID of the derivative IP to be approved
/// @param approved Result of the approval
function _setApproval(
address licensorIpId,
uint256 licenseId,
address childIpId,
bool approved
) internal verifyPermission(licensorIpId) {
_approvals[licenseId][licensorIpId][childIpId] = approved;
emit DerivativeApproved(licenseId, licensorIpId, msg.sender, approved);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
/**
* @dev Muldiv operation overflow.
*/
error MathOverflowedMulDiv();
enum Rounding {
Floor, // Toward negative infinity
Ceil, // Toward positive infinity
Trunc, // Toward zero
Expand // Away from zero
}
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an overflow flag.
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds towards infinity instead
* of rounding towards zero.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
if (b == 0) {
// Guarantee the same behavior as in a regular Solidity division.
return a / b;
}
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
* denominator == 0.
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
* Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0 = x * y; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
if (denominator <= prod1) {
revert MathOverflowedMulDiv();
}
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator.
// Always >= 1. See https://cs.stackexchange.com/q/138556/92363.
uint256 twos = denominator & (0 - denominator);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
// works in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
* towards zero.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256 of a positive value rounded towards zero.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);
}
}
/**
* @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
*/
function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
return uint8(rounding) % 2 == 1;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard signed math utilities missing in the Solidity language.
*/
library SignedMath {
/**
* @dev Returns the largest of two signed numbers.
*/
function max(int256 a, int256 b) internal pure returns (int256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two signed numbers.
*/
function min(int256 a, int256 b) internal pure returns (int256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two signed numbers without overflow.
* The result is rounded towards zero.
*/
function average(int256 a, int256 b) internal pure returns (int256) {
// Formula from the book "Hacker's Delight"
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
/**
* @dev Returns the absolute unsigned value of a signed value.
*/
function abs(int256 n) internal pure returns (uint256) {
unchecked {
// must be unchecked in order to support `n = type(int256).min`
return uint256(n >= 0 ? n : -n);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
/// @notice Module Interface
interface IModule is IERC165 {
/// @notice Returns the string identifier associated with the module.
function name() external returns (string memory);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";
import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import { BaseModule } from "../BaseModule.sol";
import { Governable } from "../../governance/Governable.sol";
import { IRoyaltyModule } from "../../interfaces/modules/royalty/IRoyaltyModule.sol";
import { IRoyaltyPolicy } from "../../interfaces/modules/royalty/policies/IRoyaltyPolicy.sol";
import { Errors } from "../../lib/Errors.sol";
import { ROYALTY_MODULE_KEY } from "../../lib/modules/Module.sol";
import { BaseModule } from "../BaseModule.sol";
/// @title Story Protocol Royalty Module
/// @notice The Story Protocol royalty module allows to set royalty policies an IP asset and pay royalties as a
/// derivative IP.
contract RoyaltyModule is IRoyaltyModule, Governable, ReentrancyGuard, BaseModule {
using ERC165Checker for address;
string public constant override name = ROYALTY_MODULE_KEY;
/// @notice Returns the licensing module address
address public LICENSING_MODULE;
/// @notice Indicates if a royalty policy is whitelisted
mapping(address royaltyPolicy => bool isWhitelisted) public isWhitelistedRoyaltyPolicy;
/// @notice Indicates if a royalty token is whitelisted
mapping(address token => bool) public isWhitelistedRoyaltyToken;
/// @notice Indicates the royalty policy for a given IP asset
mapping(address ipId => address royaltyPolicy) public royaltyPolicies;
constructor(address governance) Governable(governance) {}
/// @notice Modifier to enforce that the caller is the licensing module
modifier onlyLicensingModule() {
if (msg.sender != LICENSING_MODULE) revert Errors.RoyaltyModule__NotAllowedCaller();
_;
}
/// @notice Sets the license registry
/// @dev Enforced to be only callable by the protocol admin
/// @param licensingModule The address of the license registry
function setLicensingModule(address licensingModule) external onlyProtocolAdmin {
if (licensingModule == address(0)) revert Errors.RoyaltyModule__ZeroLicensingModule();
LICENSING_MODULE = licensingModule;
}
/// @notice Whitelist a royalty policy
/// @dev Enforced to be only callable by the protocol admin
/// @param royaltyPolicy The address of the royalty policy
/// @param allowed Indicates if the royalty policy is whitelisted or not
function whitelistRoyaltyPolicy(address royaltyPolicy, bool allowed) external onlyProtocolAdmin {
if (royaltyPolicy == address(0)) revert Errors.RoyaltyModule__ZeroRoyaltyPolicy();
isWhitelistedRoyaltyPolicy[royaltyPolicy] = allowed;
emit RoyaltyPolicyWhitelistUpdated(royaltyPolicy, allowed);
}
/// @notice Whitelist a royalty token
/// @dev Enforced to be only callable by the protocol admin
/// @param token The token address
/// @param allowed Indicates if the token is whitelisted or not
function whitelistRoyaltyToken(address token, bool allowed) external onlyProtocolAdmin {
if (token == address(0)) revert Errors.RoyaltyModule__ZeroRoyaltyToken();
isWhitelistedRoyaltyToken[token] = allowed;
emit RoyaltyTokenWhitelistUpdated(token, allowed);
}
/// @notice Executes royalty related logic on license minting
/// @dev Enforced to be only callable by LicensingModule
/// @param ipId The ipId whose license is being minted (licensor)
/// @param royaltyPolicy The royalty policy address of the license being minted
/// @param licenseData The license data custom to each the royalty policy
/// @param externalData The external data custom to each the royalty policy
function onLicenseMinting(
address ipId,
address royaltyPolicy,
bytes calldata licenseData,
bytes calldata externalData
) external nonReentrant onlyLicensingModule {
if (!isWhitelistedRoyaltyPolicy[royaltyPolicy]) revert Errors.RoyaltyModule__NotWhitelistedRoyaltyPolicy();
address royaltyPolicyIpId = royaltyPolicies[ipId];
// if the node is a root node, then royaltyPolicyIpId will be address(0) and any type of royalty type can be
// selected to mint a license if the node is a derivative node, then the any minted licenses by the derivative
// node should have the same royalty policy as the parent node a derivative node set its royalty policy
// immutably in onLinkToParents() function below
if (royaltyPolicyIpId != royaltyPolicy && royaltyPolicyIpId != address(0))
revert Errors.RoyaltyModule__CanOnlyMintSelectedPolicy();
IRoyaltyPolicy(royaltyPolicy).onLicenseMinting(ipId, licenseData, externalData);
}
/// @notice Executes royalty related logic on linking to parents
/// @dev Enforced to be only callable by LicensingModule
/// @param ipId The children ipId that is being linked to parents
/// @param royaltyPolicy The common royalty policy address of all the licenses being burned
/// @param parentIpIds The parent ipIds that the children ipId is being linked to
/// @param licenseData The license data custom to each the royalty policy
/// @param externalData The external data custom to each the royalty policy
function onLinkToParents(
address ipId,
address royaltyPolicy,
address[] calldata parentIpIds,
bytes[] memory licenseData,
bytes calldata externalData
) external nonReentrant onlyLicensingModule {
if (!isWhitelistedRoyaltyPolicy[royaltyPolicy]) revert Errors.RoyaltyModule__NotWhitelistedRoyaltyPolicy();
if (parentIpIds.length == 0) revert Errors.RoyaltyModule__NoParentsOnLinking();
for (uint32 i = 0; i < parentIpIds.length; i++) {
address parentRoyaltyPolicy = royaltyPolicies[parentIpIds[i]];
// if the parent node has a royalty policy set, then the derivative node should have the same royalty
// policy if the parent node does not have a royalty policy set, then the derivative node can set any type
// of royalty policy as long as the children ip obtained and is burning all licenses with that royalty type
// from each parent (was checked in licensing module before calling this function)
if (parentRoyaltyPolicy != royaltyPolicy && parentRoyaltyPolicy != address(0))
revert Errors.RoyaltyModule__IncompatibleRoyaltyPolicy();
}
royaltyPolicies[ipId] = royaltyPolicy;
IRoyaltyPolicy(royaltyPolicy).onLinkToParents(ipId, parentIpIds, licenseData, externalData);
}
/// @notice Allows the function caller to pay royalties to the receiver IP asset on behalf of the payer IP asset.
/// @param receiverIpId The ipId that receives the royalties
/// @param payerIpId The ipId that pays the royalties
/// @param token The token to use to pay the royalties
/// @param amount The amount to pay
function payRoyaltyOnBehalf(
address receiverIpId,
address payerIpId,
address token,
uint256 amount
) external nonReentrant {
if (!isWhitelistedRoyaltyToken[token]) revert Errors.RoyaltyModule__NotWhitelistedRoyaltyToken();
address payerRoyaltyPolicy = royaltyPolicies[payerIpId];
// if the payer does not have a royalty policy set, then the payer is not a derivative ip and does not pay
// royalties the receiver ip can have a zero royalty policy since that could mean it is an ip a root
if (payerRoyaltyPolicy == address(0)) revert Errors.RoyaltyModule__NoRoyaltyPolicySet();
if (!isWhitelistedRoyaltyPolicy[payerRoyaltyPolicy]) revert Errors.RoyaltyModule__NotWhitelistedRoyaltyPolicy();
IRoyaltyPolicy(payerRoyaltyPolicy).onRoyaltyPayment(msg.sender, receiverIpId, token, amount);
emit RoyaltyPaid(receiverIpId, payerIpId, msg.sender, token, amount);
}
/// @notice Allows to pay the minting fee for a license
/// @param receiverIpId The ipId that receives the royalties
/// @param payerAddress The address that pays the royalties
/// @param licenseRoyaltyPolicy The royalty policy of the license being minted
/// @param token The token to use to pay the royalties
/// @param amount The amount to pay
function payLicenseMintingFee(
address receiverIpId,
address payerAddress,
address licenseRoyaltyPolicy,
address token,
uint256 amount
) external onlyLicensingModule {
if (!isWhitelistedRoyaltyToken[token]) revert Errors.RoyaltyModule__NotWhitelistedRoyaltyToken();
if (licenseRoyaltyPolicy == address(0)) revert Errors.RoyaltyModule__NoRoyaltyPolicySet();
if (!isWhitelistedRoyaltyPolicy[licenseRoyaltyPolicy])
revert Errors.RoyaltyModule__NotWhitelistedRoyaltyPolicy();
IRoyaltyPolicy(licenseRoyaltyPolicy).onRoyaltyPayment(payerAddress, receiverIpId, token, amount);
emit LicenseMintingFeePaid(receiverIpId, payerAddress, token, amount);
}
/// @notice IERC165 interface support.
function supportsInterface(bytes4 interfaceId) public view virtual override(BaseModule, IERC165) returns (bool) {
return interfaceId == type(IRoyaltyModule).interfaceId || super.supportsInterface(interfaceId);
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
import { IERC1155 } from "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import { Licensing } from "../../lib/Licensing.sol";
import { IDisputeModule } from "../modules/dispute/IDisputeModule.sol";
import { ILicensingModule } from "../modules/licensing/ILicensingModule.sol";
/// @title ILicenseRegistry
interface ILicenseRegistry is IERC1155 {
/// @notice Emitted when a license is minted
/// @param creator The address that created the license
/// @param receiver The address that received the license
/// @param licenseId The ID of the license
/// @param amount The amount of licenses minted
/// @param licenseData The license data
event LicenseMinted(
address indexed creator,
address indexed receiver,
uint256 indexed licenseId,
uint256 amount,
Licensing.License licenseData
);
/// @notice Returns the canonical protocol-wide LicensingModule
function LICENSING_MODULE() external view returns (ILicensingModule);
/// @notice Returns the canonical protocol-wide DisputeModule
function DISPUTE_MODULE() external view returns (IDisputeModule);
/// @notice Mints license NFTs representing a policy granted by a set of ipIds (licensors). This NFT needs to be
/// burned in order to link a derivative IP with its parents. If this is the first combination of policy and
/// licensors, a new licenseId will be created. If not, the license is fungible and an id will be reused.
/// @dev Only callable by the licensing module.
/// @param policyId The ID of the policy to be minted
/// @param licensorIpId_ The ID of the IP granting the license (ie. licensor)
/// @param transferable True if the license is transferable
/// @param amount Number of licenses to mint. License NFT is fungible for same policy and same licensors
/// @param receiver Receiver address of the minted license NFT(s).
/// @return licenseId The ID of the minted license NFT(s).
function mintLicense(
uint256 policyId,
address licensorIpId_,
bool transferable,
uint256 amount,
address receiver
) external returns (uint256 licenseId);
/// @notice Burns licenses
/// @param holder The address that holds the licenses
/// @param licenseIds The ids of the licenses to burn
function burnLicenses(address holder, uint256[] calldata licenseIds) external;
///
/// Getters
///
/// @notice Returns the number of licenses registered in the protocol.
/// @dev Token ID counter total count.
/// @return mintedLicenses The number of minted licenses
function mintedLicenses() external view returns (uint256);
/// @notice Returns true if holder has positive balance for the given license ID.
/// @return isLicensee True if holder is the licensee for the license (owner of the license NFT), or derivative IP
/// owner if the license was added to the IP by linking (burning a license).
function isLicensee(uint256 licenseId, address holder) external view returns (bool);
/// @notice Returns the license data for the given license ID
/// @param licenseId The ID of the license
/// @return licenseData The license data
function license(uint256 licenseId) external view returns (Licensing.License memory);
/// @notice Returns the ID of the IP asset that is the licensor of the given license ID
/// @param licenseId The ID of the license
/// @return licensorIpId The ID of the licensor
function licensorIpId(uint256 licenseId) external view returns (address);
/// @notice Returns the policy ID for the given license ID
/// @param licenseId The ID of the license
/// @return policyId The ID of the policy
function policyIdForLicense(uint256 licenseId) external view returns (uint256);
/// @notice Returns true if the license has been revoked (licensor tagged after a dispute in
/// the dispute module). If the tag is removed, the license is not revoked anymore.
/// @param licenseId The id of the license to check
/// @return isRevoked True if the license is revoked
function isLicenseRevoked(uint256 licenseId) external view returns (bool);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
/// @title Dispute Module Interface
interface IDisputeModule {
/// @notice Dispute struct
/// @param targetIpId The ipId that is the target of the dispute
/// @param disputeInitiator The address of the dispute initiator
/// @param arbitrationPolicy The address of the arbitration policy
/// @param linkToDisputeEvidence The link of the dispute evidence
/// @param targetTag The target tag of the dispute
/// @param currentTag The current tag of the dispute
struct Dispute {
address targetIpId;
address disputeInitiator;
address arbitrationPolicy;
bytes32 linkToDisputeEvidence;
bytes32 targetTag;
bytes32 currentTag;
}
/// @notice Event emitted when a dispute tag whitelist status is updated
/// @param tag The dispute tag
/// @param allowed Indicates if the dispute tag is whitelisted
event TagWhitelistUpdated(bytes32 tag, bool allowed);
/// @notice Event emitted when an arbitration policy whitelist status is updated
/// @param arbitrationPolicy The address of the arbitration policy
/// @param allowed Indicates if the arbitration policy is whitelisted
event ArbitrationPolicyWhitelistUpdated(address arbitrationPolicy, bool allowed);
/// @notice Event emitted when an arbitration relayer whitelist status is updated
/// @param arbitrationPolicy The address of the arbitration policy
/// @param arbitrationRelayer The address of the arbitration relayer
/// @param allowed Indicates if the arbitration relayer is whitelisted
event ArbitrationRelayerWhitelistUpdated(address arbitrationPolicy, address arbitrationRelayer, bool allowed);
/// @notice Event emitted when the base arbitration policy is set
/// @param arbitrationPolicy The address of the arbitration policy
event DefaultArbitrationPolicyUpdated(address arbitrationPolicy);
/// @notice Event emitted when an arbitration policy is set for an ipId
/// @param ipId The ipId address
/// @param arbitrationPolicy The address of the arbitration policy
event ArbitrationPolicySet(address ipId, address arbitrationPolicy);
/// @notice Event emitted when a dispute is raised
/// @param disputeId The dispute id
/// @param targetIpId The ipId that is the target of the dispute
/// @param disputeInitiator The address of the dispute initiator
/// @param arbitrationPolicy The address of the arbitration policy
/// @param linkToDisputeEvidence The link of the dispute evidence
/// @param targetTag The target tag of the dispute
/// @param data Custom data adjusted to each policy
event DisputeRaised(
uint256 disputeId,
address targetIpId,
address disputeInitiator,
address arbitrationPolicy,
bytes32 linkToDisputeEvidence,
bytes32 targetTag,
bytes data
);
/// @notice Event emitted when a dispute judgement is set
/// @param disputeId The dispute id
/// @param decision The decision of the dispute
/// @param data Custom data adjusted to each policy
event DisputeJudgementSet(uint256 disputeId, bool decision, bytes data);
/// @notice Event emitted when a dispute is cancelled
/// @param disputeId The dispute id
/// @param data Custom data adjusted to each policy
event DisputeCancelled(uint256 disputeId, bytes data);
/// @notice Event emitted when a dispute is resolved
/// @param disputeId The dispute id
event DisputeResolved(uint256 disputeId);
/// @notice Tag to represent the dispute is in dispute state waiting for judgement
function IN_DISPUTE() external view returns (bytes32);
/// @notice Dispute ID counter
function disputeCounter() external view returns (uint256);
/// @notice The address of the base arbitration policy
function baseArbitrationPolicy() external view returns (address);
/// @notice Returns the dispute information for a given dispute id
/// @param disputeId The dispute id
/// @return targetIpId The ipId that is the target of the dispute
/// @return disputeInitiator The address of the dispute initiator
/// @return arbitrationPolicy The address of the arbitration policy
/// @return linkToDisputeEvidence The link of the dispute summary
/// @return targetTag The target tag of the dispute
/// @return currentTag The current tag of the dispute
function disputes(
uint256 disputeId
)
external
view
returns (
address targetIpId,
address disputeInitiator,
address arbitrationPolicy,
bytes32 linkToDisputeEvidence,
bytes32 targetTag,
bytes32 currentTag
);
/// @notice Indicates if a dispute tag is whitelisted
/// @param tag The dispute tag
/// @return allowed Indicates if the dispute tag is whitelisted
function isWhitelistedDisputeTag(bytes32 tag) external view returns (bool allowed);
/// @notice Indicates if an arbitration policy is whitelisted
/// @param arbitrationPolicy The address of the arbitration policy
/// @return allowed Indicates if the arbitration policy is whitelisted
function isWhitelistedArbitrationPolicy(address arbitrationPolicy) external view returns (bool allowed);
/// @notice Indicates if an arbitration relayer is whitelisted for a given arbitration policy
/// @param arbitrationPolicy The address of the arbitration policy
/// @param arbitrationRelayer The address of the arbitration relayer
/// @return allowed Indicates if the arbitration relayer is whitelisted
function isWhitelistedArbitrationRelayer(
address arbitrationPolicy,
address arbitrationRelayer
) external view returns (bool allowed);
/// @notice Arbitration policy for a given ipId
/// @param ipId The ipId
/// @return policy The address of the arbitration policy
function arbitrationPolicies(address ipId) external view returns (address policy);
/// @notice Whitelists a dispute tag
/// @param tag The dispute tag
/// @param allowed Indicates if the dispute tag is whitelisted or not
function whitelistDisputeTag(bytes32 tag, bool allowed) external;
/// @notice Whitelists an arbitration policy
/// @param arbitrationPolicy The address of the arbitration policy
/// @param allowed Indicates if the arbitration policy is whitelisted or not
function whitelistArbitrationPolicy(address arbitrationPolicy, bool allowed) external;
/// @notice Whitelists an arbitration relayer for a given arbitration policy
/// @param arbitrationPolicy The address of the arbitration policy
/// @param arbPolicyRelayer The address of the arbitration relayer
/// @param allowed Indicates if the arbitration relayer is whitelisted or not
function whitelistArbitrationRelayer(address arbitrationPolicy, address arbPolicyRelayer, bool allowed) external;
/// @notice Sets the base arbitration policy
/// @param arbitrationPolicy The address of the arbitration policy
function setBaseArbitrationPolicy(address arbitrationPolicy) external;
/// @notice Sets the arbitration policy for an ipId
/// @param ipId The ipId
/// @param arbitrationPolicy The address of the arbitration policy
function setArbitrationPolicy(address ipId, address arbitrationPolicy) external;
/// @notice Raises a dispute on a given ipId
/// @param targetIpId The ipId that is the target of the dispute
/// @param linkToDisputeEvidence The link of the dispute evidence
/// @param targetTag The target tag of the dispute
/// @param data The data to initialize the policy
/// @return disputeId The id of the newly raised dispute
function raiseDispute(
address targetIpId,
string memory linkToDisputeEvidence,
bytes32 targetTag,
bytes calldata data
) external returns (uint256 disputeId);
/// @notice Sets the dispute judgement on a given dispute. Only whitelisted arbitration relayers can call to judge.
/// @param disputeId The dispute id
/// @param decision The decision of the dispute
/// @param data The data to set the dispute judgement
function setDisputeJudgement(uint256 disputeId, bool decision, bytes calldata data) external;
/// @notice Cancels an ongoing dispute
/// @param disputeId The dispute id
/// @param data The data to cancel the dispute
function cancelDispute(uint256 disputeId, bytes calldata data) external;
/// @notice Resolves a dispute after it has been judged
/// @param disputeId The dispute id
function resolveDispute(uint256 disputeId) external;
/// @notice Returns true if the ipId is tagged with any tag (meaning at least one dispute went through)
/// @param ipId The ipId
/// @return isTagged True if the ipId is tagged
function isIpTagged(address ipId) external view returns (bool);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
import { IERC165 } from "@openzeppelin/contracts/interfaces/IERC165.sol";
/// @title IPolicyFrameworkManager
/// @notice Interface to define a policy framework contract, that will register itself into the LicenseRegistry to
/// format policy into the LicenseRegistry
interface IPolicyFrameworkManager is IERC165 {
/// @notice Name to be show in LNFT metadata
function name() external view returns (string memory);
/// @notice Returns the URL to the off chain legal agreement template text
function licenseTextUrl() external view returns (string memory);
/// @notice Returns the stringified JSON policy data for the LicenseRegistry.uri(uint256) method.
/// @dev Must return ERC1155 OpenSea standard compliant metadata.
/// @param policyData The encoded licensing policy data to be decoded by the PFM
/// @return jsonString The OpenSea-compliant metadata URI of the policy
function policyToJson(bytes memory policyData) external view returns (string memory);
/// @notice Verify compatibility of one or more policies when inheriting them from one or more parent IPs.
/// @dev Enforced to be only callable by LicenseRegistry
/// @dev The assumption in this method is that we can add parents later on, hence the need
/// for an aggregator, if not we will do this when linking to parents directly with an
/// array of policies.
/// @param aggregator common state of the policies for the IP
/// @param policyId the ID of the policy being inherited
/// @param policy the policy to inherit
/// @return changedAgg true if the aggregator was changed
/// @return newAggregator the new aggregator
function processInheritedPolicies(
bytes memory aggregator,
uint256 policyId,
bytes memory policy
) external view returns (bool changedAgg, bytes memory newAggregator);
/// @notice Verify policy parameters for minting a license.
/// @dev Enforced to be only callable by LicenseRegistry
/// @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 licensee,
bool mintingFromADerivative,
address licensorIpId,
address receiver,
uint256 mintAmount,
bytes memory policyData
) external returns (bool);
/// @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 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 licensee,
address ipId,
address parentIpId,
bytes calldata policyData
) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
// contracts
import { ILicensingModule } from "../../interfaces/modules/licensing/ILicensingModule.sol";
import { Errors } from "../../lib/Errors.sol";
/// @title LicensingModuleAware
/// @notice Base contract to be inherited by modules that need to access the licensing module.
abstract contract LicensingModuleAware {
/// @notice Returns the protocol-wide licensing module.
ILicensingModule public immutable LICENSING_MODULE;
constructor(address licensingModule) {
LICENSING_MODULE = ILicensingModule(licensingModule);
}
/// @notice Modifier for authorizing the calling entity to only the LicensingModule.
modifier onlyLicensingModule() {
if (msg.sender != address(LICENSING_MODULE)) {
revert Errors.LicensingModuleAware__CallerNotLicensingModule();
}
_;
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
import { IAccessController } from "../interfaces/IAccessController.sol";
import { IPAccountChecker } from "../lib/registries/IPAccountChecker.sol";
import { IIPAccountRegistry } from "../interfaces/registries/IIPAccountRegistry.sol";
import { Errors } from "../lib/Errors.sol";
/// @title AccessControlled
/// @notice Provides a base contract for access control functionalities.
/// @dev This abstract contract implements basic access control mechanisms with an emphasis
/// on IP account verification and permission checks.
/// It is designed to be used as a base contract for other contracts that require access control.
/// It provides modifiers and functions to verify if the caller has the necessary permission
/// and is a registered IP account.
abstract contract AccessControlled {
using IPAccountChecker for IIPAccountRegistry;
/// @notice The IAccessController instance for permission checks.
IAccessController public immutable ACCESS_CONTROLLER;
/// @notice The IIPAccountRegistry instance for IP account verification.
IIPAccountRegistry public immutable IP_ACCOUNT_REGISTRY;
/// @dev Initializes the contract by setting the ACCESS_CONTROLLER and IP_ACCOUNT_REGISTRY addresses.
/// @param accessController The address of the AccessController contract.
/// @param ipAccountRegistry The address of the IPAccountRegistry contract.
constructor(address accessController, address ipAccountRegistry) {
if (accessController == address(0)) revert Errors.AccessControlled__ZeroAddress();
if (ipAccountRegistry == address(0)) revert Errors.AccessControlled__ZeroAddress();
ACCESS_CONTROLLER = IAccessController(accessController);
IP_ACCOUNT_REGISTRY = IIPAccountRegistry(ipAccountRegistry);
}
/// @notice Verifies that the caller has the necessary permission for the given IPAccount.
/// @dev Modifier that calls _verifyPermission to check if the provided IP account has the required permission.
/// modules can use this modifier to check if the caller has the necessary permission.
/// @param ipAccount The address of the IP account to verify.
modifier verifyPermission(address ipAccount) {
_verifyPermission(ipAccount);
_;
}
/// @notice Ensures that the caller is a registered IP account.
/// @dev Modifier that checks if the msg.sender is a registered IP account.
/// modules can use this modifier to check if the caller is a registered IP account.
/// so that enforce only registered IP Account can call the functions.
modifier onlyIpAccount() {
if (!IP_ACCOUNT_REGISTRY.isIpAccount(msg.sender)) {
revert Errors.AccessControlled__CallerIsNotIpAccount(msg.sender);
}
_;
}
/// @dev Internal function to verify if the caller (msg.sender) has the required permission to execute
/// the function on provided ipAccount.
/// @param ipAccount The address of the IP account to verify.
function _verifyPermission(address ipAccount) internal view {
if (!IP_ACCOUNT_REGISTRY.isIpAccount(ipAccount)) {
revert Errors.AccessControlled__NotIpAccount(ipAccount);
}
if (msg.sender != ipAccount) {
// revert if the msg.sender does not have permission
ACCESS_CONTROLLER.checkPermission(ipAccount, msg.sender, address(this), msg.sig);
}
}
/// @dev Internal function to check if the caller (msg.sender) has the required permission to execute
/// the function on provided ipAccount, returning a boolean.
/// @param ipAccount The address of the IP account to check.
/// @return bool Returns true if the caller has permission, false otherwise.
function _hasPermission(address ipAccount) internal view returns (bool) {
if (!IP_ACCOUNT_REGISTRY.isIpAccount(ipAccount)) {
return false;
}
if (msg.sender == ipAccount) {
return true;
}
try ACCESS_CONTROLLER.checkPermission(ipAccount, msg.sender, address(this), msg.sig) {
return true;
} catch {
return false;
}
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
import { IERC165, ERC165 } from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import { IModule } from "../interfaces/modules/base/IModule.sol";
/// @title BaseModule
/// @notice Base implementation for all modules in Story Protocol.
abstract contract BaseModule is ERC165, IModule {
/// @notice IERC165 interface support.
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return interfaceId == type(IModule).interfaceId || super.supportsInterface(interfaceId);
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";
import { Errors } from "../lib/Errors.sol";
import { IGovernance } from "../interfaces/governance/IGovernance.sol";
import { IGovernable } from "../interfaces/governance/IGovernable.sol";
import { GovernanceLib } from "../lib/GovernanceLib.sol";
/// @title Governable
/// @dev All contracts managed by governance should inherit from this contract.
abstract contract Governable is IGovernable {
/// @notice The address of the governance.
address public governance;
/// @dev Ensures that the function is called by the protocol admin.
modifier onlyProtocolAdmin() {
if (!IGovernance(governance).hasRole(GovernanceLib.PROTOCOL_ADMIN, msg.sender)) {
revert Errors.Governance__OnlyProtocolAdmin();
}
_;
}
modifier whenNotPaused() {
if (IGovernance(governance).getState() == GovernanceLib.ProtocolState.Paused) {
revert Errors.Governance__ProtocolPaused();
}
_;
}
/// @notice Constructs a new Governable contract.
/// @param governance_ The address of the governance.
constructor(address governance_) {
if (governance_ == address(0)) revert Errors.Governance__ZeroAddress();
governance = governance_;
emit GovernanceUpdated(governance);
}
/// @notice Sets a new governance address.
/// @param newGovernance The address of the new governance.
function setGovernance(address newGovernance) external onlyProtocolAdmin {
if (newGovernance == address(0)) revert Errors.Governance__ZeroAddress();
if (!ERC165Checker.supportsInterface(newGovernance, type(IGovernance).interfaceId))
revert Errors.Governance__UnsupportedInterface("IGovernance");
if (IGovernance(newGovernance).getState() != IGovernance(governance).getState())
revert Errors.Governance__InconsistentState();
governance = newGovernance;
emit GovernanceUpdated(newGovernance);
}
/// @notice Returns the current governance address.
/// @return governance The address of the current governance.
function getGovernance() external view returns (address) {
return governance;
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
import { IModule } from "../../modules/base/IModule.sol";
/// @title RoyaltyModule interface
interface IRoyaltyModule is IModule {
/// @notice Event emitted when a royalty policy is whitelisted
/// @param royaltyPolicy The address of the royalty policy
/// @param allowed Indicates if the royalty policy is whitelisted or not
event RoyaltyPolicyWhitelistUpdated(address royaltyPolicy, bool allowed);
/// @notice Event emitted when a royalty token is whitelisted
/// @param token The address of the royalty token
/// @param allowed Indicates if the royalty token is whitelisted or not
event RoyaltyTokenWhitelistUpdated(address token, bool allowed);
/// @notice Event emitted when royalties are paid
/// @param receiverIpId The ID of IP asset that receives the royalties
/// @param payerIpId The ID of IP asset that pays the royalties
/// @param sender The address that pays the royalties on behalf of the payer ID of IP asset
/// @param token The token that is used to pay the royalties
/// @param amount The amount that is paid
event RoyaltyPaid(address receiverIpId, address payerIpId, address sender, address token, uint256 amount);
/// @notice Event emitted when the license minting fee is paid
/// @param receiverIpId The ipId that receives the royalties
/// @param payerAddress The address that pays the royalties
/// @param token The token that is used to pay the royalties
/// @param amount The amount paid
event LicenseMintingFeePaid(address receiverIpId, address payerAddress, address token, uint256 amount);
/// @notice Returns the licensing module address
function LICENSING_MODULE() external view returns (address);
/// @notice Indicates if a royalty policy is whitelisted
/// @param royaltyPolicy The address of the royalty policy
/// @return isWhitelisted True if the royalty policy is whitelisted
function isWhitelistedRoyaltyPolicy(address royaltyPolicy) external view returns (bool);
/// @notice Indicates if a royalty token is whitelisted
/// @param token The address of the royalty token
/// @return isWhitelisted True if the royalty token is whitelisted
function isWhitelistedRoyaltyToken(address token) external view returns (bool);
/// @notice Indicates the royalty policy for a given IP asset
/// @param ipId The ID of IP asset
/// @return royaltyPolicy The address of the royalty policy
function royaltyPolicies(address ipId) external view returns (address);
/// @notice Whitelist a royalty policy
/// @dev Enforced to be only callable by the protocol admin
/// @param royaltyPolicy The address of the royalty policy
/// @param allowed Indicates if the royalty policy is whitelisted or not
function whitelistRoyaltyPolicy(address royaltyPolicy, bool allowed) external;
/// @notice Whitelist a royalty token
/// @dev Enforced to be only callable by the protocol admin
/// @param token The token address
/// @param allowed Indicates if the token is whitelisted or not
function whitelistRoyaltyToken(address token, bool allowed) external;
/// @notice Executes royalty related logic on license minting
/// @dev Enforced to be only callable by LicensingModule
/// @param ipId The ipId whose license is being minted (licensor)
/// @param royaltyPolicy The royalty policy address of the license being minted
/// @param licenseData The license data custom to each the royalty policy
/// @param externalData The external data custom to each the royalty policy
function onLicenseMinting(
address ipId,
address royaltyPolicy,
bytes calldata licenseData,
bytes calldata externalData
) external;
/// @notice Executes royalty related logic on linking to parents
/// @dev Enforced to be only callable by LicensingModule
/// @param ipId The children ipId that is being linked to parents
/// @param royaltyPolicy The common royalty policy address of all the licenses being burned
/// @param parentIpIds The parent ipIds that the children ipId is being linked to
/// @param licenseData The license data custom to each the royalty policy
/// @param externalData The external data custom to each the royalty policy
function onLinkToParents(
address ipId,
address royaltyPolicy,
address[] calldata parentIpIds,
bytes[] memory licenseData,
bytes calldata externalData
) external;
/// @notice Allows the function caller to pay royalties to the receiver IP asset on behalf of the payer IP asset.
/// @param receiverIpId The ID of the IP asset that receives the royalties
/// @param payerIpId The ID of the IP asset that pays the royalties
/// @param token The token to use to pay the royalties
/// @param amount The amount to pay
function payRoyaltyOnBehalf(address receiverIpId, address payerIpId, address token, uint256 amount) external;
/// @notice Allows to pay the minting fee for a license
/// @param receiverIpId The ipId that receives the royalties
/// @param payerAddress The address that pays the royalties
/// @param licenseRoyaltyPolicy The royalty policy of the license being minted
/// @param token The token to use to pay the royalties
/// @param amount The amount to pay
function payLicenseMintingFee(
address receiverIpId,
address payerAddress,
address licenseRoyaltyPolicy,
address token,
uint256 amount
) external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
/// @title RoyaltyPolicy interface
interface IRoyaltyPolicy {
/// @notice Executes royalty related logic on minting a license
/// @dev Enforced to be only callable by RoyaltyModule
/// @param ipId The ipId whose license is being minted (licensor)
/// @param licenseData The license data custom to each the royalty policy
/// @param externalData The external data custom to each the royalty policy
function onLicenseMinting(address ipId, bytes calldata licenseData, bytes calldata externalData) external;
/// @notice Executes royalty related logic on linking to parents
/// @dev Enforced to be only callable by RoyaltyModule
/// @param ipId The children ipId that is being linked to parents
/// @param parentIpIds The parent ipIds that the children ipId is being linked to
/// @param licenseData The license data custom to each the royalty policy
/// @param externalData The external data custom to each the royalty policy
function onLinkToParents(
address ipId,
address[] calldata parentIpIds,
bytes[] memory licenseData,
bytes calldata externalData
) external;
/// @notice Allows the caller to pay royalties to the given IP asset
/// @param caller The caller is the address from which funds will transferred from
/// @param ipId The ipId of the receiver of the royalties
/// @param token The token to pay
/// @param amount The amount to pay
function onRoyaltyPayment(address caller, address ipId, address token, uint256 amount) external;
}// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.23; // Default Module Type, all modules in this type by default string constant MODULE_TYPE_DEFAULT = "MODULE"; string constant MODULE_TYPE_HOOK = "HOOK_MODULE"; // String values for core protocol modules. string constant IP_RESOLVER_MODULE_KEY = "IP_RESOLVER_MODULE"; // String values for core protocol modules. string constant REGISTRATION_MODULE_KEY = "REGISTRATION_MODULE"; // String values for core protocol modules. string constant LICENSING_MODULE_KEY = "LICENSING_MODULE"; // String values for core protocol modules. string constant DISPUTE_MODULE_KEY = "DISPUTE_MODULE"; string constant ROYALTY_MODULE_KEY = "ROYALTY_MODULE"; string constant TOKEN_WITHDRAWAL_MODULE_KEY = "TOKEN_MANAGEMENT_MODULE";
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (token/ERC1155/IERC1155.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC1155 compliant contract, as defined in the
* https://eips.ethereum.org/EIPS/eip-1155[EIP].
*/
interface IERC1155 is IERC165 {
/**
* @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.
*/
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
/**
* @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
* transfers.
*/
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] values
);
/**
* @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
* `approved`.
*/
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
/**
* @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
*
* If an {URI} event was emitted for `id`, the standard
* https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
* returned by {IERC1155MetadataURI-uri}.
*/
event URI(string value, uint256 indexed id);
/**
* @dev Returns the value of tokens of token type `id` owned by `account`.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function balanceOf(address account, uint256 id) external view returns (uint256);
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
*
* Requirements:
*
* - `accounts` and `ids` must have the same length.
*/
function balanceOfBatch(
address[] calldata accounts,
uint256[] calldata ids
) external view returns (uint256[] memory);
/**
* @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
*
* Emits an {ApprovalForAll} event.
*
* Requirements:
*
* - `operator` cannot be the caller.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
*
* See {setApprovalForAll}.
*/
function isApprovedForAll(address account, address operator) external view returns (bool);
/**
* @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.
*
* WARNING: This function can potentially allow a reentrancy attack when transferring tokens
* to an untrusted contract, when invoking {onERC1155Received} on the receiver.
* Ensure to follow the checks-effects-interactions pattern and consider employing
* reentrancy guards when interacting with untrusted contracts.
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.
* - `from` must have a balance of tokens of type `id` of at least `value` amount.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
* acceptance magic value.
*/
function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
*
* WARNING: This function can potentially allow a reentrancy attack when transferring tokens
* to an untrusted contract, when invoking {onERC1155BatchReceived} on the receiver.
* Ensure to follow the checks-effects-interactions pattern and consider employing
* reentrancy guards when interacting with untrusted contracts.
*
* Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments.
*
* Requirements:
*
* - `ids` and `values` must have the same length.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
* acceptance magic value.
*/
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../utils/introspection/IERC165.sol";// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
import { AccessPermission } from "../lib/AccessPermission.sol";
interface IAccessController {
/// @notice Emitted when a permission is set.
/// @param ipAccount The address of the IP account that grants the permission for `signer`
/// @param signer The address that can call `to` on behalf of the IP account
/// @param to The address that can be called by the `signer` (currently only modules can be `to`)
/// @param func The function selector of `to` that can be called by the `signer` on behalf of the `ipAccount`
/// @param permission The permission level
event PermissionSet(
address ipAccountOwner,
address indexed ipAccount,
address indexed signer,
address indexed to,
bytes4 func,
uint8 permission
);
/// @notice Sets a batch of permissions in a single transaction.
/// @dev This function allows setting multiple permissions at once. Pausable.
/// @param permissions An array of `Permission` structs, each representing the permission to be set.
function setBatchPermissions(AccessPermission.Permission[] memory permissions) external;
/// @notice Sets the permission for all IPAccounts
/// @dev Enforced to be only callable by the protocol admin in governance.
/// @param signer The address that can call `to` on behalf of the IP account
/// @param to The address that can be called by the `signer` (currently only modules can be `to`)
/// @param func The function selector of `to` that can be called by the `signer` on behalf of the `ipAccount`
/// @param permission The new permission level
function setGlobalPermission(address signer, address to, bytes4 func, uint8 permission) external;
/// @notice Sets the permission for a specific function call
/// @dev Each policy is represented as a mapping from an IP account address to a signer address to a recipient
/// address to a function selector to a permission level. The permission level can be 0 (ABSTAIN), 1 (ALLOW), or
/// 2 (DENY).
/// @dev By default, all policies are set to 0 (ABSTAIN), which means that the permission is not set.
/// The owner of ipAccount by default has all permission.
/// address(0) => wildcard
/// bytes4(0) => wildcard
/// Specific permission overrides wildcard permission.
/// @param ipAccount The address of the IP account that grants the permission for `signer`
/// @param signer The address that can call `to` on behalf of the `ipAccount`
/// @param to The address that can be called by the `signer` (currently only modules can be `to`)
/// @param func The function selector of `to` that can be called by the `signer` on behalf of the `ipAccount`
/// @param permission The new permission level
function setPermission(address ipAccount, address signer, address to, bytes4 func, uint8 permission) external;
/// @notice Checks the permission level for a specific function call. Reverts if permission is not granted.
/// Otherwise, the function is a noop.
/// @dev This function checks the permission level for a specific function call.
/// If a specific permission is set, it overrides the general (wildcard) permission.
/// If the current level permission is ABSTAIN, the final permission is determined by the upper level.
/// @param ipAccount The address of the IP account that grants the permission for `signer`
/// @param signer The address that can call `to` on behalf of the `ipAccount`
/// @param to The address that can be called by the `signer` (currently only modules can be `to`)
/// @param func The function selector of `to` that can be called by the `signer` on behalf of the `ipAccount`
function checkPermission(address ipAccount, address signer, address to, bytes4 func) external view;
/// @notice Returns the permission level for a specific function call.
/// @param ipAccount The address of the IP account that grants the permission for `signer`
/// @param signer The address that can call `to` on behalf of the `ipAccount`
/// @param to The address that can be called by the `signer` (currently only modules can be `to`)
/// @param func The function selector of `to` that can be called by the `signer` on behalf of the `ipAccount`
/// @return permission The current permission level for the function call on `to` by the `signer` for `ipAccount`
function getPermission(address ipAccount, address signer, address to, bytes4 func) external view returns (uint8);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";
import { IERC6551Account } from "erc6551/interfaces/IERC6551Account.sol";
import { IIPAccountRegistry } from "../../interfaces/registries/IIPAccountRegistry.sol";
import { IIPAccount } from "../..//interfaces/IIPAccount.sol";
/// @title IPAccountChecker
/// @dev This library provides utility functions to check the registration and validity of IP Accounts.
/// It uses the ERC165 standard for contract introspection and the IIPAccountRegistry interface
/// for account registration checks.
library IPAccountChecker {
/// @notice Returns true if the IPAccount is registered.
/// @param chainId_ The chain ID where the IP Account is located.
/// @param tokenContract_ The address of the token contract associated with the IP Account.
/// @param tokenId_ The ID of the token associated with the IP Account.
/// @return True if the IP Account is registered, false otherwise.
function isRegistered(
IIPAccountRegistry ipAccountRegistry_,
uint256 chainId_,
address tokenContract_,
uint256 tokenId_
) external view returns (bool) {
return ipAccountRegistry_.ipAccount(chainId_, tokenContract_, tokenId_).code.length != 0;
}
/// @notice Checks if the given address is a valid IP Account.
/// @param ipAccountRegistry_ The IP Account registry contract.
/// @param ipAccountAddress_ The address to check.
/// @return True if the address is a valid IP Account, false otherwise.
function isIpAccount(
IIPAccountRegistry ipAccountRegistry_,
address ipAccountAddress_
) external view returns (bool) {
if (ipAccountAddress_ == address(0)) return false;
if (ipAccountAddress_.code.length == 0) return false;
if (!ERC165Checker.supportsERC165(ipAccountAddress_)) return false;
if (!ERC165Checker.supportsInterface(ipAccountAddress_, type(IERC6551Account).interfaceId)) return false;
if (!ERC165Checker.supportsInterface(ipAccountAddress_, type(IIPAccount).interfaceId)) return false;
(uint chainId, address tokenContract, uint tokenId) = IIPAccount(payable(ipAccountAddress_)).token();
return ipAccountAddress_ == ipAccountRegistry_.ipAccount(chainId, tokenContract, tokenId);
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
/// @title Interface for IP Account Registry
/// @notice This interface manages the registration and tracking of IP Accounts
interface IIPAccountRegistry {
/// @notice Event emitted when a new IP Account is created
/// @param account The address of the new IP Account
/// @param implementation The address of the IP Account implementation
/// @param chainId The chain ID where the token contract was deployed
/// @param tokenContract The address of the token contract associated with the IP Account
/// @param tokenId The ID of the token associated with the IP Account
event IPAccountRegistered(
address indexed account,
address indexed implementation,
uint256 indexed chainId,
address tokenContract,
uint256 tokenId
);
/// @notice Returns the IPAccount implementation address
function IP_ACCOUNT_IMPL() external view returns (address);
/// @notice Returns the IPAccount salt
function IP_ACCOUNT_SALT() external view returns (bytes32);
/// @notice Returns the public ERC6551 registry address
function ERC6551_PUBLIC_REGISTRY() external view returns (address);
/// @notice Deploys an IPAccount contract with the IPAccount implementation and returns the address of the new IP
/// @dev The IPAccount deployment deltegates to public ERC6551 Registry
/// @param chainId The chain ID where the IP Account will be created
/// @param tokenContract The address of the token contract to be associated with the IP Account
/// @param tokenId The ID of the token to be associated with the IP Account
/// @return ipAccountAddress The address of the newly created IP Account
function registerIpAccount(uint256 chainId, address tokenContract, uint256 tokenId) external returns (address);
/// @notice Returns the IPAccount address for the given NFT token.
/// @param chainId The chain ID where the IP Account is located
/// @param tokenContract The address of the token contract associated with the IP Account
/// @param tokenId The ID of the token associated with the IP Account
/// @return ipAccountAddress The address of the IP Account associated with the given NFT token
function ipAccount(uint256 chainId, address tokenContract, uint256 tokenId) external view returns (address);
/// @notice Returns the IPAccount implementation address.
/// @return The address of the IPAccount implementation
function getIPAccountImpl() external view returns (address);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
import { IAccessControl } from "@openzeppelin/contracts/access/IAccessControl.sol";
import { GovernanceLib } from "../../lib/GovernanceLib.sol";
/// @title IGovernance
/// @dev This interface defines the governance functionality for the protocol.
interface IGovernance is IAccessControl {
/// @notice Emitted when the protocol state is set
/// @param account The address that triggered the state change
/// @param prevState The previous state of the protocol
/// @param newState The new state of the protocol
/// @param timestamp The time when the state change occurred
event StateSet(
address indexed account,
GovernanceLib.ProtocolState prevState,
GovernanceLib.ProtocolState newState,
uint256 timestamp
);
/// @notice Sets the state of the protocol
/// @dev This function can only be called by an account with the appropriate role
/// @param newState The new state to set for the protocol
function setState(GovernanceLib.ProtocolState newState) external;
/// @notice Returns the current state of the protocol
/// @return state The current state of the protocol
function getState() external view returns (GovernanceLib.ProtocolState);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
/// @title IGovernable
/// @notice This is the interface for the Lens Protocol main governance functions.
interface IGovernable {
/// @notice Emitted when the governance is updated
/// @param newGovernance The address of the new governance
event GovernanceUpdated(address indexed newGovernance);
/// @notice Sets the governance address
/// @param newGovernance The address of the new governance
function setGovernance(address newGovernance) external;
/// @notice Returns the current governance address
/// @return The address of the current governance
function getGovernance() external view returns (address);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
/// @title Governance
/// @dev This library provides types for Story Protocol Governance.
library GovernanceLib {
bytes32 public constant PROTOCOL_ADMIN = bytes32(0);
/// @notice An enum containing the different states the protocol can be in.
/// @param Unpaused The unpaused state.
/// @param Paused The paused state.
enum ProtocolState {
Unpaused,
Paused
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
/// @title Access Permission Library
/// @notice Library for IPAccount access control permissions.
/// These permissions are used by the AccessController.
library AccessPermission {
/// @notice ABSTAIN means having not enough information to make decision at current level, deferred decision to up
/// level permission.
uint8 public constant ABSTAIN = 0;
/// @notice ALLOW means the permission is granted to transaction signer to call the function.
uint8 public constant ALLOW = 1;
/// @notice DENY means the permission is denied to transaction signer to call the function.
uint8 public constant DENY = 2;
/// @notice This struct is used to represent permissions in batch operations within the AccessController.
/// @param ipAccount The address of the IP account that grants the permission for `signer`
/// @param signer The address that can call `to` on behalf of the `ipAccount`
/// @param to The address that can be called by the `signer` (currently only modules can be `to`)
/// @param func The function selector of `to` that can be called by the `signer` on behalf of the `ipAccount`
/// @param permission The permission level for the transaction (0 = ABSTAIN, 1 = ALLOW, 2 = DENY).
struct Permission {
address ipAccount;
address signer;
address to;
bytes4 func;
uint8 permission;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @dev the ERC-165 identifier for this interface is `0x6faff5f1`
interface IERC6551Account {
/**
* @dev Allows the account to receive Ether.
*
* Accounts MUST implement a `receive` function.
*
* Accounts MAY perform arbitrary logic to restrict conditions
* under which Ether can be received.
*/
receive() external payable;
/**
* @dev Returns the identifier of the non-fungible token which owns the account.
*
* The return value of this function MUST be constant - it MUST NOT change over time.
*
* @return chainId The EIP-155 ID of the chain the token exists on
* @return tokenContract The contract address of the token
* @return tokenId The ID of the token
*/
function token()
external
view
returns (uint256 chainId, address tokenContract, uint256 tokenId);
/**
* @dev Returns a value that SHOULD be modified each time the account changes state.
*
* @return The current account state
*/
function state() external view returns (uint256);
/**
* @dev Returns a magic value indicating whether a given signer is authorized to act on behalf
* of the account.
*
* MUST return the bytes4 magic value 0x523e3260 if the given signer is valid.
*
* By default, the holder of the non-fungible token the account is bound to MUST be considered
* a valid signer.
*
* Accounts MAY implement additional authorization logic which invalidates the holder as a
* signer or grants signing permissions to other non-holder accounts.
*
* @param signer The address to check signing authorization for
* @param context Additional data used to determine whether the signer is valid
* @return magicValue Magic value indicating whether the signer is valid
*/
function isValidSigner(address signer, bytes calldata context)
external
view
returns (bytes4 magicValue);
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;
import { IERC721Receiver } from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import { IERC1155Receiver } from "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol";
import { IERC6551Account } from "erc6551/interfaces/IERC6551Account.sol";
/// @title IIPAccount
/// @dev IPAccount is a token-bound account that adopts the EIP-6551 standard.
/// These accounts are deployed at deterministic addresses through the official 6551 account registry.
/// As a deployed smart contract, IPAccount can store IP-related information,
/// like ownership of other NFTs such as license NFT or Royalty NFT.
/// IPAccount can interact with modules by making calls as a normal transaction sender.
/// This allows for seamless operations on the state and data of IP.
/// IPAccount is core identity for all actions.
interface IIPAccount is IERC6551Account, IERC721Receiver, IERC1155Receiver {
/// @notice Emitted when a transaction is executed.
/// @param to The recipient of the transaction.
/// @param value The amount of Ether sent.
/// @param data The data sent along with the transaction.
/// @param nonce The nonce of the transaction.
event Executed(address indexed to, uint256 value, bytes data, uint256 nonce);
/// @notice Emitted when a transaction is executed on behalf of the signer.
/// @param to The recipient of the transaction.
/// @param value The amount of Ether sent.
/// @param data The data sent along with the transaction.
/// @param nonce The nonce of the transaction.
/// @param deadline The deadline of the transaction signature.
/// @param signer The signer of the transaction.
/// @param signature The signature of the transaction, EIP-712 encoded.
event ExecutedWithSig(
address indexed to,
uint256 value,
bytes data,
uint256 nonce,
uint256 deadline,
address indexed signer,
bytes signature
);
/// @notice Returns the IPAccount's internal nonce for transaction ordering.
function state() external view returns (uint256);
/// @notice Returns the identifier of the non-fungible token which owns the account
/// @return chainId The EIP-155 ID of the chain the token exists on
/// @return tokenContract The contract address of the token
/// @return tokenId The ID of the token
function token() external view returns (uint256, address, uint256);
/// @notice Checks if the signer is valid for the given data
/// @param signer The signer to check
/// @param data The data to check against
/// @return The function selector if the signer is valid, 0 otherwise
function isValidSigner(address signer, bytes calldata data) external view returns (bytes4);
/// @notice Returns the owner of the IP Account.
/// @return owner The address of the owner.
function owner() external view returns (address);
/// @notice Executes a transaction from the IP Account on behalf of the signer.
/// @param to The recipient of the transaction.
/// @param value The amount of Ether to send.
/// @param data The data to send along with the transaction.
/// @param signer The signer of the transaction.
/// @param deadline The deadline of the transaction signature.
/// @param signature The signature of the transaction, EIP-712 encoded.
/// @return result The return data from the transaction.
function executeWithSig(
address to,
uint256 value,
bytes calldata data,
address signer,
uint256 deadline,
bytes calldata signature
) external payable returns (bytes memory);
/// @notice Executes a transaction from the IP Account.
/// @param to The recipient of the transaction.
/// @param value The amount of Ether to send.
/// @param data The data to send along with the transaction.
/// @return result The return data from the transaction.
function execute(address to, uint256 value, bytes calldata data) external payable returns (bytes memory);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)
pragma solidity ^0.8.20;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControl {
/**
* @dev The `account` is missing a role.
*/
error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);
/**
* @dev The caller of a function is not the expected one.
*
* NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
*/
error AccessControlBadConfirmation();
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*/
function renounceRole(bytes32 role, address callerConfirmation) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721Receiver.sol)
pragma solidity ^0.8.20;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be
* reverted.
*
* The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/IERC1155Receiver.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../../utils/introspection/IERC165.sol";
/**
* @dev Interface that must be implemented by smart contracts in order to receive
* ERC-1155 token transfers.
*/
interface IERC1155Receiver is IERC165 {
/**
* @dev Handles the receipt of a single ERC1155 token type. This function is
* called at the end of a `safeTransferFrom` after the balance has been updated.
*
* NOTE: To accept the transfer, this must return
* `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
* (i.e. 0xf23a6e61, or its own function selector).
*
* @param operator The address which initiated the transfer (i.e. msg.sender)
* @param from The address which previously owned the token
* @param id The ID of the token being transferred
* @param value The amount of tokens being transferred
* @param data Additional data with no specified format
* @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
*/
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external returns (bytes4);
/**
* @dev Handles the receipt of a multiple ERC1155 token types. This function
* is called at the end of a `safeBatchTransferFrom` after the balances have
* been updated.
*
* NOTE: To accept the transfer(s), this must return
* `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
* (i.e. 0xbc197c81, or its own function selector).
*
* @param operator The address which initiated the batch transfer (i.e. msg.sender)
* @param from The address which previously owned the token
* @param ids An array containing ids of each token being transferred (order and length must match values array)
* @param values An array containing amounts of each token being transferred (order and length must match ids array)
* @param data Additional data with no specified format
* @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
*/
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external returns (bytes4);
}{
"remappings": [
"@ethereum-waffle/=node_modules/@ethereum-waffle/",
"@openzeppelin/=node_modules/@openzeppelin/",
"forge-std/=node_modules/forge-std/src/",
"ds-test/=node_modules/ds-test/src/",
"base64-sol/=node_modules/base64-sol/",
"eth-gas-reporter/=node_modules/eth-gas-reporter/",
"hardhat-deploy/=node_modules/hardhat-deploy/",
"hardhat/=node_modules/hardhat/",
"erc6551/=node_modules/erc6551/",
"openzeppelin-contracts/=lib/reference/lib/openzeppelin-contracts/",
"reference/=lib/reference/"
],
"optimizer": {
"enabled": true,
"runs": 20000
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "paris",
"libraries": {
"contracts/lib/registries/IPAccountChecker.sol": {
"IPAccountChecker": "0x36e93affeca875ebcef53e922a4b716ad2a508a9"
}
}
}Contract ABI
API[{"inputs":[{"internalType":"address","name":"accessController","type":"address"},{"internalType":"address","name":"ipAccountRegistry","type":"address"},{"internalType":"address","name":"licensing","type":"address"},{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"licenseUrl_","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"ipAccount","type":"address"}],"name":"AccessControlled__NotIpAccount","type":"error"},{"inputs":[],"name":"AccessControlled__ZeroAddress","type":"error"},{"inputs":[],"name":"LicensingModuleAware__CallerNotLicensingModule","type":"error"},{"inputs":[],"name":"PILPolicyFrameworkManager__CommercialDisabled_CantAddAttribution","type":"error"},{"inputs":[],"name":"PILPolicyFrameworkManager__CommercialDisabled_CantAddCommercializers","type":"error"},{"inputs":[],"name":"PILPolicyFrameworkManager__CommercialDisabled_CantAddMintingFee","type":"error"},{"inputs":[],"name":"PILPolicyFrameworkManager__CommercialDisabled_CantAddMintingFeeToken","type":"error"},{"inputs":[],"name":"PILPolicyFrameworkManager__CommercialDisabled_CantAddRevShare","type":"error"},{"inputs":[],"name":"PILPolicyFrameworkManager__CommercialDisabled_CantAddRoyaltyPolicy","type":"error"},{"inputs":[],"name":"PILPolicyFrameworkManager__CommercialEnabled_RoyaltyPolicyRequired","type":"error"},{"inputs":[],"name":"PILPolicyFrameworkManager__CommercialValueMismatch","type":"error"},{"inputs":[],"name":"PILPolicyFrameworkManager__DerivativesDisabled_CantAddApproval","type":"error"},{"inputs":[],"name":"PILPolicyFrameworkManager__DerivativesDisabled_CantAddAttribution","type":"error"},{"inputs":[],"name":"PILPolicyFrameworkManager__DerivativesDisabled_CantAddReciprocal","type":"error"},{"inputs":[],"name":"PILPolicyFrameworkManager__ReciprocalButDifferentPolicyIds","type":"error"},{"inputs":[],"name":"PILPolicyFrameworkManager__ReciprocalValueMismatch","type":"error"},{"inputs":[],"name":"PILPolicyFrameworkManager__RightsNotFound","type":"error"},{"inputs":[],"name":"PILPolicyFrameworkManager__StringArrayMismatch","type":"error"},{"inputs":[{"internalType":"address","name":"commercializer","type":"address"}],"name":"PolicyFrameworkManager__CommercializerCheckerDoesNotSupportHook","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"length","type":"uint256"}],"name":"StringsInsufficientHexLength","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"licenseId","type":"uint256"},{"indexed":true,"internalType":"address","name":"ipId","type":"address"},{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"DerivativeApproved","type":"event"},{"inputs":[],"name":"ACCESS_CONTROLLER","outputs":[{"internalType":"contract IAccessController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"IP_ACCOUNT_REGISTRY","outputs":[{"internalType":"contract IIPAccountRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LICENSE_REGISTRY","outputs":[{"internalType":"contract ILicenseRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LICENSING_MODULE","outputs":[{"internalType":"contract ILicensingModule","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"ipId","type":"address"}],"name":"getAggregator","outputs":[{"components":[{"internalType":"bool","name":"commercial","type":"bool"},{"internalType":"bool","name":"derivativesReciprocal","type":"bool"},{"internalType":"uint256","name":"lastPolicyId","type":"uint256"},{"internalType":"bytes32","name":"territoriesAcc","type":"bytes32"},{"internalType":"bytes32","name":"distributionChannelsAcc","type":"bytes32"},{"internalType":"bytes32","name":"contentRestrictionsAcc","type":"bytes32"}],"internalType":"struct PILAggregator","name":"rights","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"policyId","type":"uint256"}],"name":"getPILPolicy","outputs":[{"components":[{"internalType":"bool","name":"attribution","type":"bool"},{"internalType":"bool","name":"commercialUse","type":"bool"},{"internalType":"bool","name":"commercialAttribution","type":"bool"},{"internalType":"address","name":"commercializerChecker","type":"address"},{"internalType":"bytes","name":"commercializerCheckerData","type":"bytes"},{"internalType":"uint32","name":"commercialRevShare","type":"uint32"},{"internalType":"bool","name":"derivativesAllowed","type":"bool"},{"internalType":"bool","name":"derivativesAttribution","type":"bool"},{"internalType":"bool","name":"derivativesApproval","type":"bool"},{"internalType":"bool","name":"derivativesReciprocal","type":"bool"},{"internalType":"string[]","name":"territories","type":"string[]"},{"internalType":"string[]","name":"distributionChannels","type":"string[]"},{"internalType":"string[]","name":"contentRestrictions","type":"string[]"}],"internalType":"struct PILPolicy","name":"policy","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"licenseId","type":"uint256"},{"internalType":"address","name":"childIpId","type":"address"}],"name":"isDerivativeApproved","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"licenseTextUrl","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"policyData","type":"bytes"}],"name":"policyToJson","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"aggregator","type":"bytes"},{"internalType":"uint256","name":"policyId","type":"uint256"},{"internalType":"bytes","name":"policy","type":"bytes"}],"name":"processInheritedPolicies","outputs":[{"internalType":"bool","name":"changedAgg","type":"bool"},{"internalType":"bytes","name":"newAggregator","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bool","name":"transferable","type":"bool"},{"internalType":"address","name":"royaltyPolicy","type":"address"},{"internalType":"uint256","name":"mintingFee","type":"uint256"},{"internalType":"address","name":"mintingFeeToken","type":"address"},{"components":[{"internalType":"bool","name":"attribution","type":"bool"},{"internalType":"bool","name":"commercialUse","type":"bool"},{"internalType":"bool","name":"commercialAttribution","type":"bool"},{"internalType":"address","name":"commercializerChecker","type":"address"},{"internalType":"bytes","name":"commercializerCheckerData","type":"bytes"},{"internalType":"uint32","name":"commercialRevShare","type":"uint32"},{"internalType":"bool","name":"derivativesAllowed","type":"bool"},{"internalType":"bool","name":"derivativesAttribution","type":"bool"},{"internalType":"bool","name":"derivativesApproval","type":"bool"},{"internalType":"bool","name":"derivativesReciprocal","type":"bool"},{"internalType":"string[]","name":"territories","type":"string[]"},{"internalType":"string[]","name":"distributionChannels","type":"string[]"},{"internalType":"string[]","name":"contentRestrictions","type":"string[]"}],"internalType":"struct PILPolicy","name":"policy","type":"tuple"}],"internalType":"struct RegisterPILPolicyParams","name":"params","type":"tuple"}],"name":"registerPolicy","outputs":[{"internalType":"uint256","name":"policyId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"licenseId","type":"uint256"},{"internalType":"address","name":"childIpId","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApproval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"licenseId","type":"uint256"},{"internalType":"address","name":"licensee","type":"address"},{"internalType":"address","name":"ipId","type":"address"},{"internalType":"address","name":"parentIpId","type":"address"},{"internalType":"bytes","name":"policyData","type":"bytes"}],"name":"verifyLink","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"licensee","type":"address"},{"internalType":"bool","name":"mintingFromADerivative","type":"bool"},{"internalType":"address","name":"licensorIpId","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"mintAmount","type":"uint256"},{"internalType":"bytes","name":"policyData","type":"bytes"}],"name":"verifyMint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
6101006040523480156200001257600080fd5b506040516200434f3803806200434f83398101604081905262000035916200022b565b8484846001600160a01b031663f0ebdc836040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000076573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009c9190620002d6565b6001600160a01b03861660805282828787876000620000bc83826200038e565b506001620000cb82826200038e565b5050506001600160a01b0383169050620000f8576040516320a816ad60e01b815260040160405180910390fd5b6001600160a01b03811662000120576040516320a816ad60e01b815260040160405180910390fd5b6001600160a01b0391821660a052811660c0521660e05250506001600355506200045a9350505050565b6001600160a01b03811681146200016057600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200018b57600080fd5b81516001600160401b0380821115620001a857620001a862000163565b604051601f8301601f19908116603f01168101908282118183101715620001d357620001d362000163565b8160405283815260209250866020858801011115620001f157600080fd5b600091505b83821015620002155785820183015181830184015290820190620001f6565b6000602085830101528094505050505092915050565b600080600080600060a086880312156200024457600080fd5b855162000251816200014a565b602087015190955062000264816200014a565b604087015190945062000277816200014a565b60608701519093506001600160401b03808211156200029557600080fd5b620002a389838a0162000179565b93506080880151915080821115620002ba57600080fd5b50620002c98882890162000179565b9150509295509295909350565b600060208284031215620002e957600080fd5b8151620002f6816200014a565b9392505050565b600181811c908216806200031257607f821691505b6020821081036200033357634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000389576000816000526020600020601f850160051c81016020861015620003645750805b601f850160051c820191505b81811015620003855782815560010162000370565b5050505b505050565b81516001600160401b03811115620003aa57620003aa62000163565b620003c281620003bb8454620002fd565b8462000339565b602080601f831160018114620003fa5760008415620003e15750858301515b600019600386901b1c1916600185901b17855562000385565b600085815260208120601f198616915b828110156200042b578886015182559484019460019091019084016200040a565b50858210156200044a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e051613e75620004da6000396000818161030f01528181610ede0152610fbb01526000818161025f0152611dbd0152600081816101680152611f3001526000818161023801528181610474015281816109fa01528181610b2401528181610c9801528181610d5001526113110152613e756000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c8063af0b2eaf11610097578063e1ecbde311610066578063e1ecbde3146102d1578063eb6b3315146102e4578063f02a3111146102f7578063f0ebdc831461030a57600080fd5b8063af0b2eaf14610281578063c75e9a59146102a1578063cd6f464d146102a9578063dc96e2aa146102bc57600080fd5b80632421d9a4116100d35780632421d9a4146101af57806329a42d56146101d057806365165aa514610233578063702acd851461025a57600080fd5b806301ffc9a71461010557806306fdde031461012d5780631b00c800146101425780631b8b107314610163575b600080fd5b6101186101133660046124ab565b610331565b60405190151581526020015b60405180910390f35b6101356103ca565b604051610124919061253d565b610155610150366004612683565b610458565b6040516101249291906126f0565b61018a7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610124565b6101c26101bd36600461270b565b61089f565b604051908152602001610124565b6101e36101de366004612773565b610aa6565b6040516101249190600060c08201905082511515825260208301511515602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b61018a7f000000000000000000000000000000000000000000000000000000000000000081565b61018a7f000000000000000000000000000000000000000000000000000000000000000081565b61029461028f366004612790565b610beb565b6040516101249190612803565b610135610d21565b6101186102b7366004612953565b610d2e565b6102cf6102ca3660046129e3565b610eac565b005b6101186102df366004612a25565b610f72565b6101356102f2366004612a55565b61106b565b610118610305366004612a8a565b6112ef565b61018a7f000000000000000000000000000000000000000000000000000000000000000081565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f0c8dc8130000000000000000000000000000000000000000000000000000000014806103c457507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b600080546103d790612b3d565b80601f016020809104026020016040519081016040528092919081815260200182805461040390612b3d565b80156104505780601f1061042557610100808354040283529160200191610450565b820191906000526020600020905b81548152906001019060200180831161043357829003601f168201915b505050505081565b600060603373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146104cb576040517f4343348300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091526000848060200190518101906105139190612cd7565b9050865160000361064b576040518060c001604052808260200151151581526020018261012001511515815260200187815260200182610140015160405160200161055e9190612e54565b60405160208183030381529060405280519060200120815260200182610160015160405160200161058f9190612e54565b6040516020818303038152906040528051906020012081526020018261018001516040516020016105c09190612e54565b6040516020818303038152906040528051906020012081525091506001826040516020016106319190600060c08201905082511515825260208301511515602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b604051602081830303815290604052935093505050610897565b8680602001905181019061065f9190612e67565b9150806101200151151582602001511515146106a7576040517f3b53932500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b816020015180156106ba57508061012001515b1561070157858260400151146106fc576040517f5ba8230300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61082c565b60208101518251151590151514610744576040517f0b63cb3100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006107a383606001518361014001516040516020016107649190612e54565b604051602081830303815290604052805190602001207f569e75fc77c1a856f6daaf9e69d8a9566ca34aa47f9133711ce065a571af0cfd60001b611416565b9050826060015181146107bc5760608301819052600194505b6107da83608001518361016001516040516020016107649190612e54565b9050826080015181146107f35760808301819052600194505b6108118360a001518361018001516040516020016107649190612e54565b90508260a00151811461082a5760a08301819052600194505b505b83826040516020016108819190600060c08201905082511515825260208301511515602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b6040516020818303038152906040529350935050505b935093915050565b60006108a961148a565b6108e36108b96080840184612ef3565b6108c96040850160208601612773565b60408501356108de6080870160608801612773565b6114cd565b6108f86108f36080840184612ef3565b611869565b6040805160e08101909152600090806109146020860186612f31565b1515815230602082015260400161092e6080860186612ef3565b60405160200161093e91906130aa565b60405160208183030381529060405281526020018460200160208101906109659190612773565b73ffffffffffffffffffffffffffffffffffffffff16815260200161098d6080860186612ef3565b61099e9060c081019060a001613246565b6040805163ffffffff90921660208301520160408051601f19818403018152918152908252858101356020830152016109dd6080860160608701612773565b73ffffffffffffffffffffffffffffffffffffffff1681525090507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663032e1860826040518263ffffffff1660e01b8152600401610a519190613263565b6020604051808303816000875af1158015610a70573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a94919061330e565b915050610aa16001600355565b919050565b6040805160c081018252600080825260208201819052818301819052606082018190526080820181905260a0820181905291517f30d9113600000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff84811660248301529192917f000000000000000000000000000000000000000000000000000000000000000016906330d9113690604401600060405180830381865afa158015610b6b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b939190810190613327565b90508051600003610bd0576040517fc64675f600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80806020019051810190610be49190612e67565b9392505050565b604080516101a08101825260008082526020820181905281830181905260608083018290526080830181905260a0830182905260c0830182905260e08301829052610100830182905261012083018290526101408301819052610160830181905261018083015291517f3cea51200000000000000000000000000000000000000000000000000000000081526004810184905290919073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690633cea512090602401600060405180830381865afa158015610cdf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d07919081019061335c565b90508060400151806020019051810190610be49190612cd7565b600180546103d790612b3d565b6000610d3861148a565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610da7576040517f4343348300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082806020019051810190610dbd9190612cd7565b9050806101200151158015610dcf5750865b15610dde576000915050610e98565b606081015173ffffffffffffffffffffffffffffffffffffffff1615610e9257806060015173ffffffffffffffffffffffffffffffffffffffff16634a41d1ac8983608001516040518363ffffffff1660e01b8152600401610e4192919061343b565b6020604051808303816000875af1158015610e60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e84919061346a565b610e92576000915050610e98565b60019150505b610ea26001600355565b9695505050505050565b6040517f34d70eea000000000000000000000000000000000000000000000000000000008152600481018490526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906334d70eea90602401602060405180830381865afa158015610f3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f5e9190613487565b9050610f6c8185858561195a565b50505050565b6040517f34d70eea00000000000000000000000000000000000000000000000000000000815260048101839052600090819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906334d70eea90602401602060405180830381865afa158015611002573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110269190613487565b600094855260026020908152604080872073ffffffffffffffffffffffffffffffffffffffff9384168852825280872095909216865293909352505090205460ff1690565b60606000828060200190518101906110839190612cd7565b9050600081600001516110cb576040518060400160405280600581526020017f66616c7365000000000000000000000000000000000000000000000000000000815250611102565b6040518060400160405280600481526020017f74727565000000000000000000000000000000000000000000000000000000008152505b61110b83611a0a565b61111484611b61565b604051602001611126939291906134c0565b604051602081830303815290604052905080604051602001611148919061357e565b60408051601f198184030181529190526101408301515190915060005b818110156111ec57828461014001518281518110611185576111856135e5565b602002602001015160405160200161119e929190613614565b60408051601f1981840301815291905292506111bb6001836136a4565b81146111e457826040516020016111d291906136b7565b60405160208183030381529060405292505b600101611165565b50816040516020016111fe91906136f8565b6040516020818303038152906040529150816040516020016112209190613739565b604051602081830303815290604052915082610160015151905060005b818110156112c45782846101600151828151811061125d5761125d6135e5565b6020026020010151604051602001611276929190613614565b60408051601f1981840301815291905292506112936001836136a4565b81146112bc57826040516020016112aa91906136b7565b60405160208183030381529060405292505b60010161123d565b50816040516020016112d691906136f8565b60408051601f1981840301815291905295945050505050565b60006112f961148a565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614611368576040517f4343348300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061137683850185613835565b90508060c0015161138b576000915050610e98565b80610100015180156113a457506113a28887610f72565b155b156113b3576000915050610e98565b606081015173ffffffffffffffffffffffffffffffffffffffff1615610e9257806060015173ffffffffffffffffffffffffffffffffffffffff16634a41d1ac8883608001516040518363ffffffff1660e01b8152600401610e4192919061343b565b6000828403611426575081610be4565b8184141580156114365750818314155b1561146d576040517fe12ebaba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81841461147b575082610be4565b818314610be457509092915050565b6002600354036114c6576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600355565b6114dd6040850160208601612f31565b6116b0576114f16060850160408601612f31565b15611528576040517f7397bbaa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061153a6080860160608701612773565b73ffffffffffffffffffffffffffffffffffffffff1614611587576040517fc1f0a67d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061159960c0860160a08701613246565b63ffffffff1611156115d7576040517f529c886000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff831615611625576040517f3f63513800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b811561165d576040517f0cb7b17500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8116156116ab576040517f88fb4f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f6c565b73ffffffffffffffffffffffffffffffffffffffff83166116fd576040517f7660ada600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061170f6080860160608701612773565b73ffffffffffffffffffffffffffffffffffffffff1614610f6c5761177a7fe352692d0000000000000000000000000000000000000000000000000000000061175e6080870160608801612773565b73ffffffffffffffffffffffffffffffffffffffff1690611d64565b6117de5761178e6080850160608601612773565b6040517f5f72721800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024015b60405180910390fd5b6117ee6080850160608601612773565b73ffffffffffffffffffffffffffffffffffffffff1663a913b88161181660808701876139a1565b6040518363ffffffff1660e01b8152600401611833929190613a06565b60006040518083038186803b15801561184b57600080fd5b505afa15801561185f573d6000803e3d6000fd5b5050505050505050565b61187960e0820160c08301612f31565b6119575761188e610100820160e08301612f31565b156118c5576040517f550c495200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6118d761012082016101008301612f31565b1561190e576040517f0891883b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61192061014082016101208301612f31565b15611957576040517f209f573300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b8361196481611d80565b600084815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff898116808652918452828520908816855283529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016861515908117909155905190815233929187917f436fd071b1745141646f97213ec7dd4b24e735af0c49bd6d047186c995cc10cc910160405180910390a45050505050565b60608160200151611a50576040518060400160405280600581526020017f66616c7365000000000000000000000000000000000000000000000000000000815250611a87565b6040518060400160405280600481526020017f74727565000000000000000000000000000000000000000000000000000000008152505b8260400151611acb576040518060400160405280600581526020017f66616c7365000000000000000000000000000000000000000000000000000000815250611b02565b6040518060400160405280600481526020017f74727565000000000000000000000000000000000000000000000000000000008152505b611b158460a0015163ffffffff16611f8d565b611b38856060015173ffffffffffffffffffffffffffffffffffffffff1661204c565b604051602001611b4b9493929190613a1a565b6040516020818303038152906040529050919050565b60608160c00151611ba7576040518060400160405280600581526020017f66616c7365000000000000000000000000000000000000000000000000000000815250611bde565b6040518060400160405280600481526020017f74727565000000000000000000000000000000000000000000000000000000008152505b8260e00151611c22576040518060400160405280600581526020017f66616c7365000000000000000000000000000000000000000000000000000000815250611c59565b6040518060400160405280600481526020017f74727565000000000000000000000000000000000000000000000000000000008152505b836101000151611c9e576040518060400160405280600581526020017f66616c7365000000000000000000000000000000000000000000000000000000815250611cd5565b6040518060400160405280600481526020017f74727565000000000000000000000000000000000000000000000000000000008152505b846101200151611d1a576040518060400160405280600581526020017f66616c7365000000000000000000000000000000000000000000000000000000815250611d51565b6040518060400160405280600481526020017f74727565000000000000000000000000000000000000000000000000000000008152505b604051602001611b4b9493929190613c3d565b6000611d6f8361206f565b8015610be45750610be483836120d3565b6040517f5a1c2dd700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166004830152821660248201527336e93affeca875ebcef53e922a4b716ad2a508a990635a1c2dd790604401602060405180830381865af4158015611e26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e4a919061346a565b611e98576040517fd64edf9000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016117d5565b3373ffffffffffffffffffffffffffffffffffffffff821614611957576040517f7dfd0ddb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301523360248301523060448301526000357fffffffff000000000000000000000000000000000000000000000000000000001660648301527f00000000000000000000000000000000000000000000000000000000000000001690637dfd0ddb9060840160006040518083038186803b158015611f7257600080fd5b505afa158015611f86573d6000803e3d6000fd5b5050505050565b60606000611f9a836121a3565b600101905060008167ffffffffffffffff811115611fba57611fba612550565b6040519080825280601f01601f191660200182016040528015611fe4576020820181803683370190505b5090508181016020015b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff017f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8504945084611fee575b509392505050565b60606103c473ffffffffffffffffffffffffffffffffffffffff83166014612285565b600061209b827f01ffc9a7000000000000000000000000000000000000000000000000000000006120d3565b80156103c457506120cc827fffffffff000000000000000000000000000000000000000000000000000000006120d3565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825192935060009283928392909183918a617530fa92503d9150600051905082801561218c575060208210155b80156121985750600081115b979650505050505050565b6000807a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106121ec577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000830492506040015b6d04ee2d6d415b85acef81000000008310612218576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061223657662386f26fc10000830492506010015b6305f5e100831061224e576305f5e100830492506008015b612710831061226257612710830492506004015b60648310612274576064830492506002015b600a83106103c45760010192915050565b6060826000612295846002613de0565b6122a0906002613df7565b67ffffffffffffffff8111156122b8576122b8612550565b6040519080825280601f01601f1916602001820160405280156122e2576020820181803683370190505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110612319576123196135e5565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061237c5761237c6135e5565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060006123b8856002613de0565b6123c3906001613df7565b90505b6001811115612460577f303132333435363738396162636465660000000000000000000000000000000083600f1660108110612404576124046135e5565b1a60f81b82828151811061241a5761241a6135e5565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049290921c9161245981613e0a565b90506123c6565b5081156124a3576040517fe22e27eb00000000000000000000000000000000000000000000000000000000815260048101869052602481018590526044016117d5565b949350505050565b6000602082840312156124bd57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610be457600080fd5b60005b838110156125085781810151838201526020016124f0565b50506000910152565b600081518084526125298160208601602086016124ed565b601f01601f19169290920160200192915050565b602081526000610be46020830184612511565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516101a0810167ffffffffffffffff811182821017156125a3576125a3612550565b60405290565b60405160e0810167ffffffffffffffff811182821017156125a3576125a3612550565b604051601f8201601f1916810167ffffffffffffffff811182821017156125f5576125f5612550565b604052919050565b600067ffffffffffffffff82111561261757612617612550565b50601f01601f191660200190565b6000612638612633846125fd565b6125cc565b905082815283838301111561264c57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261267457600080fd5b610be483833560208501612625565b60008060006060848603121561269857600080fd5b833567ffffffffffffffff808211156126b057600080fd5b6126bc87838801612663565b94506020860135935060408601359150808211156126d957600080fd5b506126e686828701612663565b9150509250925092565b82151581526040602082015260006124a36040830184612511565b60006020828403121561271d57600080fd5b813567ffffffffffffffff81111561273457600080fd5b820160a08185031215610be457600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116811461195757600080fd5b8035610aa181612746565b60006020828403121561278557600080fd5b8135610be481612746565b6000602082840312156127a257600080fd5b5035919050565b60008282518085526020808601955060208260051b8401016020860160005b848110156127f657601f198684030189526127e4838351612511565b988401989250908301906001016127c8565b5090979650505050505050565b6020815261281660208201835115159052565b6000602083015161282b604084018215159052565b506040830151801515606084015250606083015173ffffffffffffffffffffffffffffffffffffffff811660808401525060808301516101a08060a08501526128786101c0850183612511565b915060a085015161289160c086018263ffffffff169052565b5060c085015180151560e08601525060e08501516101006128b58187018315159052565b86015190506101206128ca8682018315159052565b86015190506101406128df8682018315159052565b80870151915050601f196101608187860301818801526128ff85846127a9565b94508088015192505061018081878603018188015261291e85846127a9565b908801518782039092018488015293509050610ea283826127a9565b801515811461195757600080fd5b8035610aa18161293a565b60008060008060008060c0878903121561296c57600080fd5b863561297781612746565b955060208701356129878161293a565b9450604087013561299781612746565b935060608701356129a781612746565b92506080870135915060a087013567ffffffffffffffff8111156129ca57600080fd5b6129d689828a01612663565b9150509295509295509295565b6000806000606084860312156129f857600080fd5b833592506020840135612a0a81612746565b91506040840135612a1a8161293a565b809150509250925092565b60008060408385031215612a3857600080fd5b823591506020830135612a4a81612746565b809150509250929050565b600060208284031215612a6757600080fd5b813567ffffffffffffffff811115612a7e57600080fd5b6124a384828501612663565b60008060008060008060a08789031215612aa357600080fd5b863595506020870135612ab581612746565b94506040870135612ac581612746565b93506060870135612ad581612746565b9250608087013567ffffffffffffffff80821115612af257600080fd5b818901915089601f830112612b0657600080fd5b813581811115612b1557600080fd5b8a6020828501011115612b2757600080fd5b6020830194508093505050509295509295509295565b600181811c90821680612b5157607f821691505b602082108103612b8a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8051610aa18161293a565b8051610aa181612746565b6000612bb4612633846125fd565b9050828152838383011115612bc857600080fd5b610be48360208301846124ed565b600082601f830112612be757600080fd5b610be483835160208501612ba6565b63ffffffff8116811461195757600080fd5b8051610aa181612bf6565b600067ffffffffffffffff821115612c2d57612c2d612550565b5060051b60200190565b600082601f830112612c4857600080fd5b81516020612c5861263383612c13565b82815260059290921b84018101918181019086841115612c7757600080fd5b8286015b84811015612ccc57805167ffffffffffffffff811115612c9b5760008081fd5b8701603f81018913612cad5760008081fd5b612cbe898683015160408401612ba6565b845250918301918301612c7b565b509695505050505050565b600060208284031215612ce957600080fd5b815167ffffffffffffffff80821115612d0157600080fd5b908301906101a08286031215612d1657600080fd5b612d1e61257f565b612d2783612b90565b8152612d3560208401612b90565b6020820152612d4660408401612b90565b6040820152612d5760608401612b9b565b6060820152608083015182811115612d6e57600080fd5b612d7a87828601612bd6565b608083015250612d8c60a08401612c08565b60a0820152612d9d60c08401612b90565b60c0820152612dae60e08401612b90565b60e0820152610100612dc1818501612b90565b90820152610120612dd3848201612b90565b908201526101408381015183811115612deb57600080fd5b612df788828701612c37565b8284015250506101608084015183811115612e1157600080fd5b612e1d88828701612c37565b8284015250506101808084015183811115612e3757600080fd5b612e4388828701612c37565b918301919091525095945050505050565b602081526000610be460208301846127a9565b600060c08284031215612e7957600080fd5b60405160c0810181811067ffffffffffffffff82111715612e9c57612e9c612550565b6040528251612eaa8161293a565b81526020830151612eba8161293a565b8060208301525060408301516040820152606083015160608201526080830151608082015260a083015160a08201528091505092915050565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe61833603018112612f2757600080fd5b9190910192915050565b600060208284031215612f4357600080fd5b8135610be48161293a565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612f8357600080fd5b830160208101925035905067ffffffffffffffff811115612fa357600080fd5b803603821315612fb257600080fd5b9250929050565b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b8035610aa181612bf6565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261302457600080fd5b830160208101925035905067ffffffffffffffff81111561304457600080fd5b8060051b3603821315612fb257600080fd5b6000838385526020808601955060208560051b8301018460005b878110156127f657601f1985840301895261308b8288612f4e565b613096858284612fb9565b9a86019a9450505090830190600101613070565b602081526130c4602082016130be84612948565b15159052565b60006130d260208401612948565b8015156040840152506130e760408401612948565b8015156060840152506130fc60608401612768565b73ffffffffffffffffffffffffffffffffffffffff81166080840152506131266080840184612f4e565b6101a08060a086015261313e6101c086018385612fb9565b925061314c60a08701612fe4565b63ffffffff811660c0870152915061316660c08701612948565b80151560e0870152915061317c60e08701612948565b915061010061318e8187018415159052565b613199818801612948565b9250506101206131ac8187018415159052565b6131b7818801612948565b9250506101406131ca8187018415159052565b6131d681880188612fef565b93509050601f196101608188870301818901526131f4868685613056565b9550613202818a018a612fef565b955092505061018081888703018189015261321e868685613056565b955061322c818a018a612fef565b955092505080878603018388015250612198848483613056565b60006020828403121561325857600080fd5b8135610be481612bf6565b602081528151151560208201526000602083015173ffffffffffffffffffffffffffffffffffffffff80821660408501526040850151915060e060608501526132b0610100850183612511565b9150806060860151166080850152506080840151601f198483030160a08501526132da8282612511565b91505060a084015160c084015260c084015161204460e085018273ffffffffffffffffffffffffffffffffffffffff169052565b60006020828403121561332057600080fd5b5051919050565b60006020828403121561333957600080fd5b815167ffffffffffffffff81111561335057600080fd5b6124a384828501612bd6565b60006020828403121561336e57600080fd5b815167ffffffffffffffff8082111561338657600080fd5b9083019060e0828603121561339a57600080fd5b6133a26125a9565b6133ab83612b90565b81526133b960208401612b9b565b60208201526040830151828111156133d057600080fd5b6133dc87828601612bd6565b6040830152506133ee60608401612b9b565b606082015260808301518281111561340557600080fd5b61341187828601612bd6565b60808301525060a083015160a082015261342d60c08401612b9b565b60c082015295945050505050565b73ffffffffffffffffffffffffffffffffffffffff831681526040602082015260006124a36040830184612511565b60006020828403121561347c57600080fd5b8151610be48161293a565b60006020828403121561349957600080fd5b8151610be481612746565b600081516134b68185602086016124ed565b9290920192915050565b7f7b2274726169745f74797065223a20224174747269627574696f6e222c20227681527f616c7565223a202200000000000000000000000000000000000000000000000060208201526000845161351e8160288501602089016124ed565b7f227d2c0000000000000000000000000000000000000000000000000000000000602891840191820152845161355b81602b8401602089016124ed565b845191019061357181602b8401602088016124ed565b01602b0195945050505050565b600082516135908184602087016124ed565b7f7b2274726169745f74797065223a20225465727269746f72696573222c2022769201918252507f616c7565223a205b0000000000000000000000000000000000000000000000006020820152602801919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600083516136268184602088016124ed565b80830190507f220000000000000000000000000000000000000000000000000000000000000080825284516136628160018501602089016124ed565b6001920191820152600201949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156103c4576103c4613675565b600082516136c98184602087016124ed565b7f2c00000000000000000000000000000000000000000000000000000000000000920191825250600101919050565b6000825161370a8184602087016124ed565b7f5d7d2c0000000000000000000000000000000000000000000000000000000000920191825250600301919050565b6000825161374b8184602087016124ed565b7f7b2274726169745f74797065223a2022446973747269627574696f6e204368619201918252507f6e6e656c73222c202276616c7565223a205b00000000000000000000000000006020820152603201919050565b600082601f8301126137b157600080fd5b813560206137c161263383612c13565b82815260059290921b840181019181810190868411156137e057600080fd5b8286015b84811015612ccc57803567ffffffffffffffff8111156138045760008081fd5b8701603f810189136138165760008081fd5b613827898683013560408401612625565b8452509183019183016137e4565b60006020828403121561384757600080fd5b813567ffffffffffffffff8082111561385f57600080fd5b908301906101a0828603121561387457600080fd5b61387c61257f565b61388583612948565b815261389360208401612948565b60208201526138a460408401612948565b60408201526138b560608401612768565b60608201526080830135828111156138cc57600080fd5b6138d887828601612663565b6080830152506138ea60a08401612fe4565b60a08201526138fb60c08401612948565b60c082015261390c60e08401612948565b60e082015261010061391f818501612948565b90820152610120613931848201612948565b90820152610140838101358381111561394957600080fd5b613955888287016137a0565b828401525050610160808401358381111561396f57600080fd5b61397b888287016137a0565b828401525050610180808401358381111561399557600080fd5b612e43888287016137a0565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126139d657600080fd5b83018035915067ffffffffffffffff8211156139f157600080fd5b602001915036819003821315612fb257600080fd5b6020815260006124a3602083018486612fb9565b7f7b2274726169745f74797065223a2022436f6d6d65726369616c20557365222c81527f202276616c7565223a2022000000000000000000000000000000000000000000602082015260008551613a7881602b850160208a016124ed565b80830190507f227d2c000000000000000000000000000000000000000000000000000000000080602b8301527f7b2274726169745f74797065223a2022436f6d6d65726369616c204174747269602e8301527f627574696f6e222c202276616c7565223a202200000000000000000000000000604e8301528651613b03816061850160208b016124ed565b60619201918201527f7b2274726169745f74797065223a2022436f6d6d65726369616c20526576656e60648201527f7565205368617265222c20226d61785f76616c7565223a20313030302c20227660848201527f616c7565223a200000000000000000000000000000000000000000000000000060a4820152612198613c14613c0e613bbf613b9660ab86018a6134a4565b7f7d2c000000000000000000000000000000000000000000000000000000000000815260020190565b7f7b2274726169745f74797065223a2022436f6d6d65726369616c697a6572204381527f6865636b222c202276616c7565223a2022000000000000000000000000000000602082015260310190565b866134a4565b7f227d2c0000000000000000000000000000000000000000000000000000000000815260030190565b7f7b2274726169745f74797065223a2022446572697661746976657320416c6c6f81527f776564222c202276616c7565223a202200000000000000000000000000000000602082015260008551613c9b816030850160208a016124ed565b80830190507f227d2c00000000000000000000000000000000000000000000000000000000008060308301527f7b2274726169745f74797065223a20224465726976617469766573204174747260338301527f69627574696f6e222c202276616c7565223a202200000000000000000000000060538301528651613d26816067850160208b016124ed565b60679201918201527f7b2274726169745f74797065223a202244657269766174697665732041707072606a8201527f6f76616c222c202276616c7565223a2022000000000000000000000000000000608a820152612198613c14613c0e613d9182609b86018a6134a4565b7f7b2274726169745f74797065223a20224465726976617469766573205265636981527f70726f63616c222c202276616c7565223a202200000000000000000000000000602082015260330190565b80820281158282048414176103c4576103c4613675565b808201808211156103c4576103c4613675565b600081613e1957613e19613675565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea2646970667358221220fc90f9839b5bffd45375fae8376b11c830bd4c45c43935ea1a1e6e88633b9d8964736f6c63430008170033000000000000000000000000ad64a4b2e18ff7d2f97af083e7b193d7dd141735000000000000000000000000bd2780f291588c8bddf7f5874988fa9d3179d560000000000000000000000000950d766a1a0afdc33c3e653c861a8765cb42dbdc00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000370696c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004d68747470733a2f2f6769746875622e636f6d2f73746f727970726f746f636f6c2f70726f746f636f6c2d636f72652f626c6f622f6d61696e2f50494c2d426574612d323032342d30322e70646600000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101005760003560e01c8063af0b2eaf11610097578063e1ecbde311610066578063e1ecbde3146102d1578063eb6b3315146102e4578063f02a3111146102f7578063f0ebdc831461030a57600080fd5b8063af0b2eaf14610281578063c75e9a59146102a1578063cd6f464d146102a9578063dc96e2aa146102bc57600080fd5b80632421d9a4116100d35780632421d9a4146101af57806329a42d56146101d057806365165aa514610233578063702acd851461025a57600080fd5b806301ffc9a71461010557806306fdde031461012d5780631b00c800146101425780631b8b107314610163575b600080fd5b6101186101133660046124ab565b610331565b60405190151581526020015b60405180910390f35b6101356103ca565b604051610124919061253d565b610155610150366004612683565b610458565b6040516101249291906126f0565b61018a7f000000000000000000000000ad64a4b2e18ff7d2f97af083e7b193d7dd14173581565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610124565b6101c26101bd36600461270b565b61089f565b604051908152602001610124565b6101e36101de366004612773565b610aa6565b6040516101249190600060c08201905082511515825260208301511515602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b61018a7f000000000000000000000000950d766a1a0afdc33c3e653c861a8765cb42dbdc81565b61018a7f000000000000000000000000bd2780f291588c8bddf7f5874988fa9d3179d56081565b61029461028f366004612790565b610beb565b6040516101249190612803565b610135610d21565b6101186102b7366004612953565b610d2e565b6102cf6102ca3660046129e3565b610eac565b005b6101186102df366004612a25565b610f72565b6101356102f2366004612a55565b61106b565b610118610305366004612a8a565b6112ef565b61018a7f000000000000000000000000c2bc7a2d5784768bded98436f2522a4931e2fbb481565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f0c8dc8130000000000000000000000000000000000000000000000000000000014806103c457507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b600080546103d790612b3d565b80601f016020809104026020016040519081016040528092919081815260200182805461040390612b3d565b80156104505780601f1061042557610100808354040283529160200191610450565b820191906000526020600020905b81548152906001019060200180831161043357829003601f168201915b505050505081565b600060603373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000950d766a1a0afdc33c3e653c861a8765cb42dbdc16146104cb576040517f4343348300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091526000848060200190518101906105139190612cd7565b9050865160000361064b576040518060c001604052808260200151151581526020018261012001511515815260200187815260200182610140015160405160200161055e9190612e54565b60405160208183030381529060405280519060200120815260200182610160015160405160200161058f9190612e54565b6040516020818303038152906040528051906020012081526020018261018001516040516020016105c09190612e54565b6040516020818303038152906040528051906020012081525091506001826040516020016106319190600060c08201905082511515825260208301511515602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b604051602081830303815290604052935093505050610897565b8680602001905181019061065f9190612e67565b9150806101200151151582602001511515146106a7576040517f3b53932500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b816020015180156106ba57508061012001515b1561070157858260400151146106fc576040517f5ba8230300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61082c565b60208101518251151590151514610744576040517f0b63cb3100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006107a383606001518361014001516040516020016107649190612e54565b604051602081830303815290604052805190602001207f569e75fc77c1a856f6daaf9e69d8a9566ca34aa47f9133711ce065a571af0cfd60001b611416565b9050826060015181146107bc5760608301819052600194505b6107da83608001518361016001516040516020016107649190612e54565b9050826080015181146107f35760808301819052600194505b6108118360a001518361018001516040516020016107649190612e54565b90508260a00151811461082a5760a08301819052600194505b505b83826040516020016108819190600060c08201905082511515825260208301511515602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b6040516020818303038152906040529350935050505b935093915050565b60006108a961148a565b6108e36108b96080840184612ef3565b6108c96040850160208601612773565b60408501356108de6080870160608801612773565b6114cd565b6108f86108f36080840184612ef3565b611869565b6040805160e08101909152600090806109146020860186612f31565b1515815230602082015260400161092e6080860186612ef3565b60405160200161093e91906130aa565b60405160208183030381529060405281526020018460200160208101906109659190612773565b73ffffffffffffffffffffffffffffffffffffffff16815260200161098d6080860186612ef3565b61099e9060c081019060a001613246565b6040805163ffffffff90921660208301520160408051601f19818403018152918152908252858101356020830152016109dd6080860160608701612773565b73ffffffffffffffffffffffffffffffffffffffff1681525090507f000000000000000000000000950d766a1a0afdc33c3e653c861a8765cb42dbdc73ffffffffffffffffffffffffffffffffffffffff1663032e1860826040518263ffffffff1660e01b8152600401610a519190613263565b6020604051808303816000875af1158015610a70573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a94919061330e565b915050610aa16001600355565b919050565b6040805160c081018252600080825260208201819052818301819052606082018190526080820181905260a0820181905291517f30d9113600000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff84811660248301529192917f000000000000000000000000950d766a1a0afdc33c3e653c861a8765cb42dbdc16906330d9113690604401600060405180830381865afa158015610b6b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b939190810190613327565b90508051600003610bd0576040517fc64675f600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80806020019051810190610be49190612e67565b9392505050565b604080516101a08101825260008082526020820181905281830181905260608083018290526080830181905260a0830182905260c0830182905260e08301829052610100830182905261012083018290526101408301819052610160830181905261018083015291517f3cea51200000000000000000000000000000000000000000000000000000000081526004810184905290919073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000950d766a1a0afdc33c3e653c861a8765cb42dbdc1690633cea512090602401600060405180830381865afa158015610cdf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d07919081019061335c565b90508060400151806020019051810190610be49190612cd7565b600180546103d790612b3d565b6000610d3861148a565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000950d766a1a0afdc33c3e653c861a8765cb42dbdc1614610da7576040517f4343348300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082806020019051810190610dbd9190612cd7565b9050806101200151158015610dcf5750865b15610dde576000915050610e98565b606081015173ffffffffffffffffffffffffffffffffffffffff1615610e9257806060015173ffffffffffffffffffffffffffffffffffffffff16634a41d1ac8983608001516040518363ffffffff1660e01b8152600401610e4192919061343b565b6020604051808303816000875af1158015610e60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e84919061346a565b610e92576000915050610e98565b60019150505b610ea26001600355565b9695505050505050565b6040517f34d70eea000000000000000000000000000000000000000000000000000000008152600481018490526000907f000000000000000000000000c2bc7a2d5784768bded98436f2522a4931e2fbb473ffffffffffffffffffffffffffffffffffffffff16906334d70eea90602401602060405180830381865afa158015610f3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f5e9190613487565b9050610f6c8185858561195a565b50505050565b6040517f34d70eea00000000000000000000000000000000000000000000000000000000815260048101839052600090819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c2bc7a2d5784768bded98436f2522a4931e2fbb416906334d70eea90602401602060405180830381865afa158015611002573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110269190613487565b600094855260026020908152604080872073ffffffffffffffffffffffffffffffffffffffff9384168852825280872095909216865293909352505090205460ff1690565b60606000828060200190518101906110839190612cd7565b9050600081600001516110cb576040518060400160405280600581526020017f66616c7365000000000000000000000000000000000000000000000000000000815250611102565b6040518060400160405280600481526020017f74727565000000000000000000000000000000000000000000000000000000008152505b61110b83611a0a565b61111484611b61565b604051602001611126939291906134c0565b604051602081830303815290604052905080604051602001611148919061357e565b60408051601f198184030181529190526101408301515190915060005b818110156111ec57828461014001518281518110611185576111856135e5565b602002602001015160405160200161119e929190613614565b60408051601f1981840301815291905292506111bb6001836136a4565b81146111e457826040516020016111d291906136b7565b60405160208183030381529060405292505b600101611165565b50816040516020016111fe91906136f8565b6040516020818303038152906040529150816040516020016112209190613739565b604051602081830303815290604052915082610160015151905060005b818110156112c45782846101600151828151811061125d5761125d6135e5565b6020026020010151604051602001611276929190613614565b60408051601f1981840301815291905292506112936001836136a4565b81146112bc57826040516020016112aa91906136b7565b60405160208183030381529060405292505b60010161123d565b50816040516020016112d691906136f8565b60408051601f1981840301815291905295945050505050565b60006112f961148a565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000950d766a1a0afdc33c3e653c861a8765cb42dbdc1614611368576040517f4343348300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061137683850185613835565b90508060c0015161138b576000915050610e98565b80610100015180156113a457506113a28887610f72565b155b156113b3576000915050610e98565b606081015173ffffffffffffffffffffffffffffffffffffffff1615610e9257806060015173ffffffffffffffffffffffffffffffffffffffff16634a41d1ac8883608001516040518363ffffffff1660e01b8152600401610e4192919061343b565b6000828403611426575081610be4565b8184141580156114365750818314155b1561146d576040517fe12ebaba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81841461147b575082610be4565b818314610be457509092915050565b6002600354036114c6576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600355565b6114dd6040850160208601612f31565b6116b0576114f16060850160408601612f31565b15611528576040517f7397bbaa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061153a6080860160608701612773565b73ffffffffffffffffffffffffffffffffffffffff1614611587576040517fc1f0a67d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061159960c0860160a08701613246565b63ffffffff1611156115d7576040517f529c886000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff831615611625576040517f3f63513800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b811561165d576040517f0cb7b17500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8116156116ab576040517f88fb4f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610f6c565b73ffffffffffffffffffffffffffffffffffffffff83166116fd576040517f7660ada600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061170f6080860160608701612773565b73ffffffffffffffffffffffffffffffffffffffff1614610f6c5761177a7fe352692d0000000000000000000000000000000000000000000000000000000061175e6080870160608801612773565b73ffffffffffffffffffffffffffffffffffffffff1690611d64565b6117de5761178e6080850160608601612773565b6040517f5f72721800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024015b60405180910390fd5b6117ee6080850160608601612773565b73ffffffffffffffffffffffffffffffffffffffff1663a913b88161181660808701876139a1565b6040518363ffffffff1660e01b8152600401611833929190613a06565b60006040518083038186803b15801561184b57600080fd5b505afa15801561185f573d6000803e3d6000fd5b5050505050505050565b61187960e0820160c08301612f31565b6119575761188e610100820160e08301612f31565b156118c5576040517f550c495200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6118d761012082016101008301612f31565b1561190e576040517f0891883b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61192061014082016101208301612f31565b15611957576040517f209f573300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50565b8361196481611d80565b600084815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff898116808652918452828520908816855283529281902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016861515908117909155905190815233929187917f436fd071b1745141646f97213ec7dd4b24e735af0c49bd6d047186c995cc10cc910160405180910390a45050505050565b60608160200151611a50576040518060400160405280600581526020017f66616c7365000000000000000000000000000000000000000000000000000000815250611a87565b6040518060400160405280600481526020017f74727565000000000000000000000000000000000000000000000000000000008152505b8260400151611acb576040518060400160405280600581526020017f66616c7365000000000000000000000000000000000000000000000000000000815250611b02565b6040518060400160405280600481526020017f74727565000000000000000000000000000000000000000000000000000000008152505b611b158460a0015163ffffffff16611f8d565b611b38856060015173ffffffffffffffffffffffffffffffffffffffff1661204c565b604051602001611b4b9493929190613a1a565b6040516020818303038152906040529050919050565b60608160c00151611ba7576040518060400160405280600581526020017f66616c7365000000000000000000000000000000000000000000000000000000815250611bde565b6040518060400160405280600481526020017f74727565000000000000000000000000000000000000000000000000000000008152505b8260e00151611c22576040518060400160405280600581526020017f66616c7365000000000000000000000000000000000000000000000000000000815250611c59565b6040518060400160405280600481526020017f74727565000000000000000000000000000000000000000000000000000000008152505b836101000151611c9e576040518060400160405280600581526020017f66616c7365000000000000000000000000000000000000000000000000000000815250611cd5565b6040518060400160405280600481526020017f74727565000000000000000000000000000000000000000000000000000000008152505b846101200151611d1a576040518060400160405280600581526020017f66616c7365000000000000000000000000000000000000000000000000000000815250611d51565b6040518060400160405280600481526020017f74727565000000000000000000000000000000000000000000000000000000008152505b604051602001611b4b9493929190613c3d565b6000611d6f8361206f565b8015610be45750610be483836120d3565b6040517f5a1c2dd700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000bd2780f291588c8bddf7f5874988fa9d3179d56081166004830152821660248201527336e93affeca875ebcef53e922a4b716ad2a508a990635a1c2dd790604401602060405180830381865af4158015611e26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e4a919061346a565b611e98576040517fd64edf9000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016117d5565b3373ffffffffffffffffffffffffffffffffffffffff821614611957576040517f7dfd0ddb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301523360248301523060448301526000357fffffffff000000000000000000000000000000000000000000000000000000001660648301527f000000000000000000000000ad64a4b2e18ff7d2f97af083e7b193d7dd1417351690637dfd0ddb9060840160006040518083038186803b158015611f7257600080fd5b505afa158015611f86573d6000803e3d6000fd5b5050505050565b60606000611f9a836121a3565b600101905060008167ffffffffffffffff811115611fba57611fba612550565b6040519080825280601f01601f191660200182016040528015611fe4576020820181803683370190505b5090508181016020015b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff017f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8504945084611fee575b509392505050565b60606103c473ffffffffffffffffffffffffffffffffffffffff83166014612285565b600061209b827f01ffc9a7000000000000000000000000000000000000000000000000000000006120d3565b80156103c457506120cc827fffffffff000000000000000000000000000000000000000000000000000000006120d3565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825192935060009283928392909183918a617530fa92503d9150600051905082801561218c575060208210155b80156121985750600081115b979650505050505050565b6000807a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106121ec577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000830492506040015b6d04ee2d6d415b85acef81000000008310612218576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061223657662386f26fc10000830492506010015b6305f5e100831061224e576305f5e100830492506008015b612710831061226257612710830492506004015b60648310612274576064830492506002015b600a83106103c45760010192915050565b6060826000612295846002613de0565b6122a0906002613df7565b67ffffffffffffffff8111156122b8576122b8612550565b6040519080825280601f01601f1916602001820160405280156122e2576020820181803683370190505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110612319576123196135e5565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f78000000000000000000000000000000000000000000000000000000000000008160018151811061237c5761237c6135e5565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060006123b8856002613de0565b6123c3906001613df7565b90505b6001811115612460577f303132333435363738396162636465660000000000000000000000000000000083600f1660108110612404576124046135e5565b1a60f81b82828151811061241a5761241a6135e5565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535060049290921c9161245981613e0a565b90506123c6565b5081156124a3576040517fe22e27eb00000000000000000000000000000000000000000000000000000000815260048101869052602481018590526044016117d5565b949350505050565b6000602082840312156124bd57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610be457600080fd5b60005b838110156125085781810151838201526020016124f0565b50506000910152565b600081518084526125298160208601602086016124ed565b601f01601f19169290920160200192915050565b602081526000610be46020830184612511565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516101a0810167ffffffffffffffff811182821017156125a3576125a3612550565b60405290565b60405160e0810167ffffffffffffffff811182821017156125a3576125a3612550565b604051601f8201601f1916810167ffffffffffffffff811182821017156125f5576125f5612550565b604052919050565b600067ffffffffffffffff82111561261757612617612550565b50601f01601f191660200190565b6000612638612633846125fd565b6125cc565b905082815283838301111561264c57600080fd5b828260208301376000602084830101529392505050565b600082601f83011261267457600080fd5b610be483833560208501612625565b60008060006060848603121561269857600080fd5b833567ffffffffffffffff808211156126b057600080fd5b6126bc87838801612663565b94506020860135935060408601359150808211156126d957600080fd5b506126e686828701612663565b9150509250925092565b82151581526040602082015260006124a36040830184612511565b60006020828403121561271d57600080fd5b813567ffffffffffffffff81111561273457600080fd5b820160a08185031215610be457600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116811461195757600080fd5b8035610aa181612746565b60006020828403121561278557600080fd5b8135610be481612746565b6000602082840312156127a257600080fd5b5035919050565b60008282518085526020808601955060208260051b8401016020860160005b848110156127f657601f198684030189526127e4838351612511565b988401989250908301906001016127c8565b5090979650505050505050565b6020815261281660208201835115159052565b6000602083015161282b604084018215159052565b506040830151801515606084015250606083015173ffffffffffffffffffffffffffffffffffffffff811660808401525060808301516101a08060a08501526128786101c0850183612511565b915060a085015161289160c086018263ffffffff169052565b5060c085015180151560e08601525060e08501516101006128b58187018315159052565b86015190506101206128ca8682018315159052565b86015190506101406128df8682018315159052565b80870151915050601f196101608187860301818801526128ff85846127a9565b94508088015192505061018081878603018188015261291e85846127a9565b908801518782039092018488015293509050610ea283826127a9565b801515811461195757600080fd5b8035610aa18161293a565b60008060008060008060c0878903121561296c57600080fd5b863561297781612746565b955060208701356129878161293a565b9450604087013561299781612746565b935060608701356129a781612746565b92506080870135915060a087013567ffffffffffffffff8111156129ca57600080fd5b6129d689828a01612663565b9150509295509295509295565b6000806000606084860312156129f857600080fd5b833592506020840135612a0a81612746565b91506040840135612a1a8161293a565b809150509250925092565b60008060408385031215612a3857600080fd5b823591506020830135612a4a81612746565b809150509250929050565b600060208284031215612a6757600080fd5b813567ffffffffffffffff811115612a7e57600080fd5b6124a384828501612663565b60008060008060008060a08789031215612aa357600080fd5b863595506020870135612ab581612746565b94506040870135612ac581612746565b93506060870135612ad581612746565b9250608087013567ffffffffffffffff80821115612af257600080fd5b818901915089601f830112612b0657600080fd5b813581811115612b1557600080fd5b8a6020828501011115612b2757600080fd5b6020830194508093505050509295509295509295565b600181811c90821680612b5157607f821691505b602082108103612b8a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8051610aa18161293a565b8051610aa181612746565b6000612bb4612633846125fd565b9050828152838383011115612bc857600080fd5b610be48360208301846124ed565b600082601f830112612be757600080fd5b610be483835160208501612ba6565b63ffffffff8116811461195757600080fd5b8051610aa181612bf6565b600067ffffffffffffffff821115612c2d57612c2d612550565b5060051b60200190565b600082601f830112612c4857600080fd5b81516020612c5861263383612c13565b82815260059290921b84018101918181019086841115612c7757600080fd5b8286015b84811015612ccc57805167ffffffffffffffff811115612c9b5760008081fd5b8701603f81018913612cad5760008081fd5b612cbe898683015160408401612ba6565b845250918301918301612c7b565b509695505050505050565b600060208284031215612ce957600080fd5b815167ffffffffffffffff80821115612d0157600080fd5b908301906101a08286031215612d1657600080fd5b612d1e61257f565b612d2783612b90565b8152612d3560208401612b90565b6020820152612d4660408401612b90565b6040820152612d5760608401612b9b565b6060820152608083015182811115612d6e57600080fd5b612d7a87828601612bd6565b608083015250612d8c60a08401612c08565b60a0820152612d9d60c08401612b90565b60c0820152612dae60e08401612b90565b60e0820152610100612dc1818501612b90565b90820152610120612dd3848201612b90565b908201526101408381015183811115612deb57600080fd5b612df788828701612c37565b8284015250506101608084015183811115612e1157600080fd5b612e1d88828701612c37565b8284015250506101808084015183811115612e3757600080fd5b612e4388828701612c37565b918301919091525095945050505050565b602081526000610be460208301846127a9565b600060c08284031215612e7957600080fd5b60405160c0810181811067ffffffffffffffff82111715612e9c57612e9c612550565b6040528251612eaa8161293a565b81526020830151612eba8161293a565b8060208301525060408301516040820152606083015160608201526080830151608082015260a083015160a08201528091505092915050565b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe61833603018112612f2757600080fd5b9190910192915050565b600060208284031215612f4357600080fd5b8135610be48161293a565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612f8357600080fd5b830160208101925035905067ffffffffffffffff811115612fa357600080fd5b803603821315612fb257600080fd5b9250929050565b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b8035610aa181612bf6565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261302457600080fd5b830160208101925035905067ffffffffffffffff81111561304457600080fd5b8060051b3603821315612fb257600080fd5b6000838385526020808601955060208560051b8301018460005b878110156127f657601f1985840301895261308b8288612f4e565b613096858284612fb9565b9a86019a9450505090830190600101613070565b602081526130c4602082016130be84612948565b15159052565b60006130d260208401612948565b8015156040840152506130e760408401612948565b8015156060840152506130fc60608401612768565b73ffffffffffffffffffffffffffffffffffffffff81166080840152506131266080840184612f4e565b6101a08060a086015261313e6101c086018385612fb9565b925061314c60a08701612fe4565b63ffffffff811660c0870152915061316660c08701612948565b80151560e0870152915061317c60e08701612948565b915061010061318e8187018415159052565b613199818801612948565b9250506101206131ac8187018415159052565b6131b7818801612948565b9250506101406131ca8187018415159052565b6131d681880188612fef565b93509050601f196101608188870301818901526131f4868685613056565b9550613202818a018a612fef565b955092505061018081888703018189015261321e868685613056565b955061322c818a018a612fef565b955092505080878603018388015250612198848483613056565b60006020828403121561325857600080fd5b8135610be481612bf6565b602081528151151560208201526000602083015173ffffffffffffffffffffffffffffffffffffffff80821660408501526040850151915060e060608501526132b0610100850183612511565b9150806060860151166080850152506080840151601f198483030160a08501526132da8282612511565b91505060a084015160c084015260c084015161204460e085018273ffffffffffffffffffffffffffffffffffffffff169052565b60006020828403121561332057600080fd5b5051919050565b60006020828403121561333957600080fd5b815167ffffffffffffffff81111561335057600080fd5b6124a384828501612bd6565b60006020828403121561336e57600080fd5b815167ffffffffffffffff8082111561338657600080fd5b9083019060e0828603121561339a57600080fd5b6133a26125a9565b6133ab83612b90565b81526133b960208401612b9b565b60208201526040830151828111156133d057600080fd5b6133dc87828601612bd6565b6040830152506133ee60608401612b9b565b606082015260808301518281111561340557600080fd5b61341187828601612bd6565b60808301525060a083015160a082015261342d60c08401612b9b565b60c082015295945050505050565b73ffffffffffffffffffffffffffffffffffffffff831681526040602082015260006124a36040830184612511565b60006020828403121561347c57600080fd5b8151610be48161293a565b60006020828403121561349957600080fd5b8151610be481612746565b600081516134b68185602086016124ed565b9290920192915050565b7f7b2274726169745f74797065223a20224174747269627574696f6e222c20227681527f616c7565223a202200000000000000000000000000000000000000000000000060208201526000845161351e8160288501602089016124ed565b7f227d2c0000000000000000000000000000000000000000000000000000000000602891840191820152845161355b81602b8401602089016124ed565b845191019061357181602b8401602088016124ed565b01602b0195945050505050565b600082516135908184602087016124ed565b7f7b2274726169745f74797065223a20225465727269746f72696573222c2022769201918252507f616c7565223a205b0000000000000000000000000000000000000000000000006020820152602801919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600083516136268184602088016124ed565b80830190507f220000000000000000000000000000000000000000000000000000000000000080825284516136628160018501602089016124ed565b6001920191820152600201949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156103c4576103c4613675565b600082516136c98184602087016124ed565b7f2c00000000000000000000000000000000000000000000000000000000000000920191825250600101919050565b6000825161370a8184602087016124ed565b7f5d7d2c0000000000000000000000000000000000000000000000000000000000920191825250600301919050565b6000825161374b8184602087016124ed565b7f7b2274726169745f74797065223a2022446973747269627574696f6e204368619201918252507f6e6e656c73222c202276616c7565223a205b00000000000000000000000000006020820152603201919050565b600082601f8301126137b157600080fd5b813560206137c161263383612c13565b82815260059290921b840181019181810190868411156137e057600080fd5b8286015b84811015612ccc57803567ffffffffffffffff8111156138045760008081fd5b8701603f810189136138165760008081fd5b613827898683013560408401612625565b8452509183019183016137e4565b60006020828403121561384757600080fd5b813567ffffffffffffffff8082111561385f57600080fd5b908301906101a0828603121561387457600080fd5b61387c61257f565b61388583612948565b815261389360208401612948565b60208201526138a460408401612948565b60408201526138b560608401612768565b60608201526080830135828111156138cc57600080fd5b6138d887828601612663565b6080830152506138ea60a08401612fe4565b60a08201526138fb60c08401612948565b60c082015261390c60e08401612948565b60e082015261010061391f818501612948565b90820152610120613931848201612948565b90820152610140838101358381111561394957600080fd5b613955888287016137a0565b828401525050610160808401358381111561396f57600080fd5b61397b888287016137a0565b828401525050610180808401358381111561399557600080fd5b612e43888287016137a0565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126139d657600080fd5b83018035915067ffffffffffffffff8211156139f157600080fd5b602001915036819003821315612fb257600080fd5b6020815260006124a3602083018486612fb9565b7f7b2274726169745f74797065223a2022436f6d6d65726369616c20557365222c81527f202276616c7565223a2022000000000000000000000000000000000000000000602082015260008551613a7881602b850160208a016124ed565b80830190507f227d2c000000000000000000000000000000000000000000000000000000000080602b8301527f7b2274726169745f74797065223a2022436f6d6d65726369616c204174747269602e8301527f627574696f6e222c202276616c7565223a202200000000000000000000000000604e8301528651613b03816061850160208b016124ed565b60619201918201527f7b2274726169745f74797065223a2022436f6d6d65726369616c20526576656e60648201527f7565205368617265222c20226d61785f76616c7565223a20313030302c20227660848201527f616c7565223a200000000000000000000000000000000000000000000000000060a4820152612198613c14613c0e613bbf613b9660ab86018a6134a4565b7f7d2c000000000000000000000000000000000000000000000000000000000000815260020190565b7f7b2274726169745f74797065223a2022436f6d6d65726369616c697a6572204381527f6865636b222c202276616c7565223a2022000000000000000000000000000000602082015260310190565b866134a4565b7f227d2c0000000000000000000000000000000000000000000000000000000000815260030190565b7f7b2274726169745f74797065223a2022446572697661746976657320416c6c6f81527f776564222c202276616c7565223a202200000000000000000000000000000000602082015260008551613c9b816030850160208a016124ed565b80830190507f227d2c00000000000000000000000000000000000000000000000000000000008060308301527f7b2274726169745f74797065223a20224465726976617469766573204174747260338301527f69627574696f6e222c202276616c7565223a202200000000000000000000000060538301528651613d26816067850160208b016124ed565b60679201918201527f7b2274726169745f74797065223a202244657269766174697665732041707072606a8201527f6f76616c222c202276616c7565223a2022000000000000000000000000000000608a820152612198613c14613c0e613d9182609b86018a6134a4565b7f7b2274726169745f74797065223a20224465726976617469766573205265636981527f70726f63616c222c202276616c7565223a202200000000000000000000000000602082015260330190565b80820281158282048414176103c4576103c4613675565b808201808211156103c4576103c4613675565b600081613e1957613e19613675565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea2646970667358221220fc90f9839b5bffd45375fae8376b11c830bd4c45c43935ea1a1e6e88633b9d8964736f6c63430008170033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000ad64a4b2e18ff7d2f97af083e7b193d7dd141735000000000000000000000000bd2780f291588c8bddf7f5874988fa9d3179d560000000000000000000000000950d766a1a0afdc33c3e653c861a8765cb42dbdc00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000370696c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004d68747470733a2f2f6769746875622e636f6d2f73746f727970726f746f636f6c2f70726f746f636f6c2d636f72652f626c6f622f6d61696e2f50494c2d426574612d323032342d30322e70646600000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : accessController (address): 0xad64a4b2e18FF7D2f97aF083E7b193d7Dd141735
Arg [1] : ipAccountRegistry (address): 0xBD2780F291588C8bDDf7F5874988fA9d3179d560
Arg [2] : licensing (address): 0x950d766A1a0afDc33c3e653C861A8765cb42DbdC
Arg [3] : name_ (string): pil
Arg [4] : licenseUrl_ (string): https://github.com/storyprotocol/protocol-core/blob/main/PIL-Beta-2024-02.pdf
-----Encoded View---------------
11 Constructor Arguments found :
Arg [0] : 000000000000000000000000ad64a4b2e18ff7d2f97af083e7b193d7dd141735
Arg [1] : 000000000000000000000000bd2780f291588c8bddf7f5874988fa9d3179d560
Arg [2] : 000000000000000000000000950d766a1a0afdc33c3e653c861a8765cb42dbdc
Arg [3] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [4] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [6] : 70696c0000000000000000000000000000000000000000000000000000000000
Arg [7] : 000000000000000000000000000000000000000000000000000000000000004d
Arg [8] : 68747470733a2f2f6769746875622e636f6d2f73746f727970726f746f636f6c
Arg [9] : 2f70726f746f636f6c2d636f72652f626c6f622f6d61696e2f50494c2d426574
Arg [10] : 612d323032342d30322e70646600000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.