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
|
|||||
---|---|---|---|---|---|---|---|---|---|
Register Policy | 8495095 | 32 days ago | IN | 0 ETH | 0.00007679 | ||||
Register Policy | 8495067 | 32 days ago | IN | 0 ETH | 0.00007678 | ||||
Register Policy | 8494969 | 32 days ago | IN | 0 ETH | 0.00007677 | ||||
Register Policy | 7497810 | 175 days ago | IN | 0 ETH | 0.00898244 | ||||
Register Policy | 6594703 | 314 days ago | IN | 0 ETH | 0.04111921 | ||||
Register Policy | 6388234 | 346 days ago | IN | 0 ETH | 0.00081615 | ||||
Register Policy | 6324753 | 357 days ago | IN | 0 ETH | 0.00001714 | ||||
Register Policy | 6323477 | 358 days ago | IN | 0 ETH | 0.00133223 | ||||
Register Policy | 6323445 | 358 days ago | IN | 0 ETH | 0.00189487 | ||||
Register Policy | 6316578 | 359 days ago | IN | 0 ETH | 0.00026619 | ||||
Register Policy | 6316212 | 359 days ago | IN | 0 ETH | 0.03986283 | ||||
Register Policy | 6316187 | 359 days ago | IN | 0 ETH | 0.03642553 | ||||
Register Policy | 6316042 | 359 days ago | IN | 0 ETH | 0.00318999 | ||||
Register Policy | 6315981 | 359 days ago | IN | 0 ETH | 0.0048554 | ||||
Register Policy | 6305283 | 360 days ago | IN | 0 ETH | 0.00032043 | ||||
Register Policy | 6304201 | 361 days ago | IN | 0 ETH | 0.00127851 | ||||
Register Policy | 6052243 | 398 days ago | IN | 0 ETH | 0.00499192 | ||||
Register Policy | 6015191 | 403 days ago | IN | 0 ETH | 0.00031063 | ||||
Register Policy | 6015152 | 403 days ago | IN | 0 ETH | 0.00027809 | ||||
Register Policy | 6015035 | 403 days ago | IN | 0 ETH | 0.00023583 | ||||
Register Policy | 6014960 | 403 days ago | IN | 0 ETH | 0.00025405 | ||||
Register Policy | 6014933 | 403 days ago | IN | 0 ETH | 0.00025145 | ||||
Register Policy | 6014931 | 403 days ago | IN | 0 ETH | 0.00021994 | ||||
Register Policy | 6014843 | 404 days ago | IN | 0 ETH | 0.00033265 | ||||
Register Policy | 6014699 | 404 days ago | IN | 0 ETH | 0.00059127 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
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 Source Code Verified (Exact Match)
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.