Polygon Sponsored slots available. Book your slot here!
More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Set Module Metad... | 56697560 | 216 days ago | IN | 0 POL | 0.00360006 |
Loading...
Loading
Contract Name:
RentableSpaceAction
Compiler Version
v0.8.21+commit.d9974bed
Optimization Enabled:
Yes with 2000 runs
Other Settings:
london EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT /* __/\\\\____________/\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\_____/\\\\\\\\\\\\\\\__/\\\\\\\\\\\_ _\/\\\\\\________/\\\\\\___/\\\\\\\\\\\\\__\/\\\////////\\\__\/\\\///////////__\/////\\\///__ _\/\\\//\\\____/\\\//\\\__/\\\/////////\\\_\/\\\______\//\\\_\/\\\_________________\/\\\_____ _\/\\\\///\\\/\\\/_\/\\\_\/\\\_______\/\\\_\/\\\_______\/\\\_\/\\\\\\\\\\\_________\/\\\_____ _\/\\\__\///\\\/___\/\\\_\/\\\\\\\\\\\\\\\_\/\\\_______\/\\\_\/\\\///////__________\/\\\_____ _\/\\\____\///_____\/\\\_\/\\\/////////\\\_\/\\\_______\/\\\_\/\\\_________________\/\\\_____ _\/\\\_____________\/\\\_\/\\\_______\/\\\_\/\\\_______/\\\__\/\\\_________________\/\\\_____ _\/\\\_____________\/\\\_\/\\\_______\/\\\_\/\\\\\\\\\\\\/___\/\\\______________/\\\\\\\\\\\_ _\///______________\///__\///________\///__\////////////_____\///______________\///////////__ */ pragma solidity ^0.8.21; import {ILensProtocol, Types} from "lens/interfaces/ILensProtocol.sol"; import {IPublicationActionModule} from "lens/interfaces/IPublicationActionModule.sol"; import {HubRestricted} from "lens/base/HubRestricted.sol"; import {LensModuleMetadataInitializable} from 'lens/modules/LensModuleMetadataInitializable.sol'; import {IERC721} from "lens/interfaces/ILensERC721.sol"; import {IModuleRegistry} from 'lens/interfaces/IModuleRegistry.sol'; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {MerkleProof} from 'openzeppelin/utils/cryptography/MerkleProof.sol'; import {IRentableSpaceAction} from "./interfaces/IRentableSpaceAction.sol"; /** * @title RentableSpaceAction * @notice This contract enables profiles to rent their publication space for advertising. Payment is done via tokens * such as BONSAI, and space is rented on a per second basis. A creator inits a post with this action module and sets * the token cost per second, the allowed category for ads, and whether open actions can also be promoted. A profile who * wants to act on this module must prove their content fits the allowed category, and specify how long they wish to * rent space for; funds are transferred and the content/open action from the pubId passed in are hotswapped with this * post's content uri / open action. * NOTE: this action requires a bespoke client integration to respect the currently hotswapped content/action * NOTE: a profile can only have one active ad space at a time, and cannot create a new one while an ad is active on * another post */ contract RentableSpaceAction is HubRestricted, LensModuleMetadataInitializable, IPublicationActionModule, IRentableSpaceAction { using SafeERC20 for IERC20; mapping (uint256 profileId => ActiveSpace space) public activeSpaces; mapping (uint256 profileId => mapping (uint256 spaceId => ActiveAd ad)) public activeAds; mapping (address => mapping (address currency => uint256 amount)) public feesEarned; mapping (uint256 profileId => bool blacklisted) public blacklistedProfiles; mapping (uint256 profileId => bool flagged) public flaggedProfiles; IModuleRegistry public immutable MODULE_REGISTRY; // verify currency for payment is whitelisted // require advertisers pay at least this amount of time; also allow bidding after this inital period uint64 public adMinDuration; uint16 public protocolFeeBps; // taken from all rented spaces uint16 public minBidIncreaseBps; // advertisers can bid higher to replace active ads, by at least this % mapping (address => uint256) internal _protocolFees; uint16 internal constant BPS_MAX = 10000; uint8 internal constant MADFI_GENESIS_COLLECTION_ID = 1; modifier onlyProfileOwnerOrDelegated(uint256 profileId) { if (_owner(profileId) != msg.sender && !ILensProtocol(HUB).isDelegatedExecutorApproved(profileId, msg.sender)) revert Unauthorized(); _; } /** * @dev contract constructor * @param hub LensHub * @param _moduleRegistry: Lens ModuleRegistry */ constructor(address hub, address _moduleRegistry) HubRestricted(hub) LensModuleMetadataInitializable(msg.sender) { if (hub == address(0) || _moduleRegistry == address(0)) revert NoZeroAddress(); MODULE_REGISTRY = IModuleRegistry(_moduleRegistry); adMinDuration = 12 hours; protocolFeeBps = 1000; // 10% minBidIncreaseBps = 2000; // 20% } /** * @notice Required by Lens Protocol */ function supportsInterface(bytes4 interfaceID) public pure override returns (bool) { return interfaceID == type(IPublicationActionModule).interfaceId || super.supportsInterface(interfaceID); } /** * @notice Initializes the action module for the given publication being published with this Action module. * @custom:permissions LensHub. * * @param profileId The profile ID of the author publishing the content with this Publication Action. * @param pubId The publication ID being published. * @param data Arbitrary data passed from the user to be decoded by the Action Module during initialization. * * @return bytes Any custom ABI-encoded data. This will be a LensHub event params that can be used by * indexers or UIs. */ function initializePublicationAction( uint256 profileId, uint256 pubId, address, // transactionExecutor bytes calldata data ) external override onlyHub returns (bytes memory) { ( address currency, bool allowOpenAction, uint256 costPerSecond, uint256 expireAt, uint16 clientFeePerActBps, uint16 referralFeePerActBps, bytes32 interestMerkleRoot ) = abi.decode(data, (address, bool, uint256, uint256, uint16, uint16, bytes32)); _verifyInitParams(profileId, currency, costPerSecond, expireAt); _verifyDelegatedExecutor(profileId); activeSpaces[profileId] = ActiveSpace({ spaceId: pubId, currency: currency, costPerSecond: costPerSecond, expireAt: expireAt, interestMerkleRoot: interestMerkleRoot, allowOpenAction: allowOpenAction, clientFeePerActBps: clientFeePerActBps, referralFeePerActBps: referralFeePerActBps }); emit InitAction(profileId, pubId, costPerSecond); return data; } /** * @notice Processes the action for a given publication. This includes the action's logic and any monetary/token * operations. * @custom:permissions LensHub. * * @param processActionParams The parameters needed to execute the publication action. * * @return bytes Any custom ABI-encoded data. This will be a LensHub event params that can be used by * indexers or UIs. */ function processPublicationAction( Types.ProcessActionParams calldata processActionParams ) external override onlyHub returns (bytes memory) { ActiveSpace memory space = activeSpaces[processActionParams.publicationActedProfileId]; if (space.spaceId == 0 || (space.expireAt != 0 && space.expireAt < block.timestamp)) revert NotFoundOrExpired(); (RentParams memory params) = abi.decode(processActionParams.actionModuleData, (RentParams)); if (params.duration == 0 || !(params.adPubId > 0 || bytes(params.adContentUri).length != 0)) { revert InitParamsInvalid(); } if (blacklistedProfiles[processActionParams.actorProfileId]) revert Unauthorized(); ActiveAd memory ad = activeAds[processActionParams.publicationActedProfileId][space.spaceId]; // get cost considering active ad's current bid (if any) and protocol fee bool activeAdExists = _isValidExpiry(ad.expireAt); ( uint256 cost, uint256 costWithFee, uint256 costPerSecond ) = _getAdCost(activeAdExists, space.costPerSecond, ad.costPerSecond, params.duration); IERC20(space.currency).safeTransferFrom(processActionParams.transactionExecutor, address(this), costWithFee); _protocolFees[space.currency] += (costWithFee - cost); if (space.interestMerkleRoot.length != 0) { _validateMerkleProof( space.interestMerkleRoot, processActionParams.actorProfileId, params.merkleProofIndex, params.merkleProof ); } if (activeAdExists) _handleRefund(processActionParams.publicationActedProfileId, ad, space.currency); if (space.clientFeePerActBps > 0 && params.clientAddress != address(0)) { cost -= _transferClientFee(cost, space.clientFeePerActBps, params.clientAddress, space.currency); cost -= _transferToReferrals(processActionParams, space.referralFeePerActBps, space.currency, cost); } _validateOpenAction(space.allowOpenAction, processActionParams.actorProfileId, params); activeAds[processActionParams.publicationActedProfileId][space.spaceId] = ActiveAd({ advertiserId: processActionParams.actorProfileId, adId: params.adPubId, adContentUri: params.adContentUri, createdAt: block.timestamp, expireAt: block.timestamp + params.duration, costPerSecond: costPerSecond, openActionModule: space.allowOpenAction ? params.openActionModule : address(0) }); address actedProfileOwner = _owner(processActionParams.publicationActedProfileId); feesEarned[actedProfileOwner][space.currency] += cost; _autoMirror(processActionParams); emit SetActiveAd( processActionParams.publicationActedProfileId, space.spaceId, processActionParams.actorProfileId, params.adPubId, params.adContentUri ); return abi.encode(processActionParams.publicationActedProfileId, space.spaceId); } /** * @notice Get the active ad content, or ad pubId & open action module (if any) for a given publication space * @param profileId The publication space profile id * @param profileId The publication space id */ function getActiveAd( uint256 profileId, uint256 pubId ) external view returns (string memory contentUri, uint256 adProfileId, uint256 adPubId, address openActionModule) { ActiveAd memory ad = activeAds[profileId][pubId]; if (!_isValidExpiry(ad.expireAt)) revert NotFoundOrExpired(); contentUri = ad.adId == 0 ? ad.adContentUri : ILensProtocol(HUB).getContentURI(ad.advertiserId, ad.adId); adProfileId = ad.advertiserId; adPubId = ad.adId; openActionModule = ad.openActionModule; } /** * @notice Allows a profile owned to withdraw any fees earned, minus the owed amount for a given active ad, if any * NOTE: we accrue fees in the contract in order to handle refunds in case of ads being outbidded or canceled */ function withdrawFeesEarned(address currency, uint256 profileId) external onlyProfileOwnerOrDelegated(profileId) { (uint256 currentPaidAmount, uint256 totalCost) = getPaidAmountsOnActiveAd(profileId); address owner = _owner(profileId); uint256 fees = feesEarned[owner][currency] - (totalCost - currentPaidAmount); if (fees == 0) revert NoFeesEarned(); feesEarned[owner][currency] -= fees; IERC20(currency).safeTransfer(owner, fees); } /** * @notice Allows the contract owner to withdraw any protocol fees earned, for the given `currency` * @param currency The currency address */ function withdrawProtocolFees(address currency) external onlyOwner { uint256 fees = _protocolFees[currency]; if (fees == 0) revert NoFeesEarned(); _protocolFees[currency] = 0; IERC20(currency).safeTransfer(msg.sender, fees); } /** * @notice Allows a profile to close their active ad space, as long as their is no active ad; users should call * #cancelActiveAd to close a space with an active ad. * @param profileId Pointer to the active space */ function closeActiveSpace(uint256 profileId) external onlyProfileOwnerOrDelegated(profileId) { ActiveSpace memory space = activeSpaces[profileId]; ActiveAd memory ad = activeAds[profileId][space.spaceId]; if (_isValidExpiry(ad.expireAt)) revert MustCancelActiveAd(space.spaceId); delete activeSpaces[profileId]; } /** * @notice Allows a profile to cancel an active ad on their space. The profile must provide a reason, as well as approve * the calculated refund amount to send back to the advertiser * @param profileId Pointer to the active space * @param actorProfileId [optional] Profile id of a bad actor, whether the advertiser or from a comment * @param reason Reason to close the active ad (see struct CancelAdReason) - to flag and potentially blacklist * @param otherReason [optional] Longer description of why to cancel (can be ipfs uri) * @param closeSpace [optional] Whether to also close the ad space, preventing future ads on it */ function cancelActiveAd( uint256 profileId, uint256 actorProfileId, CancelAdReason reason, string calldata otherReason, bool closeSpace ) external onlyProfileOwnerOrDelegated(profileId) { ActiveSpace memory space = activeSpaces[profileId]; ActiveAd memory ad = activeAds[profileId][space.spaceId]; if (!_isValidExpiry(ad.expireAt)) revert NotFoundOrExpired(); uint256 refundAmount = _handleRefund(profileId, ad, space.currency); _handleFlaggedProfile(profileId, actorProfileId, reason, ad); // clear storage delete activeAds[profileId][space.spaceId]; // to completely exit if (closeSpace) delete activeSpaces[profileId]; emit CancelActiveAd(profileId, space.spaceId, ad.adId, reason, otherReason, refundAmount, closeSpace); } function getPaidAmountsOnActiveAd( uint256 profileId ) public view returns (uint256 currentPaidAmount, uint256 totalCost) { ActiveSpace memory space = activeSpaces[profileId]; ActiveAd memory ad = activeAds[profileId][space.spaceId]; if (!_isValidExpiry(ad.expireAt)) return (0, 0); currentPaidAmount = (block.timestamp - ad.createdAt) * ad.costPerSecond; totalCost = (ad.expireAt - ad.createdAt) * ad.costPerSecond; } function getAdCost( uint256 profileId, uint256 duration ) public view returns (uint256 cost, uint256 costWithFee, uint256 costPerSecond) { ActiveSpace memory space = activeSpaces[profileId]; ActiveAd memory ad = activeAds[profileId][space.spaceId]; return _getAdCost(_isValidExpiry(ad.expireAt), space.costPerSecond, ad.costPerSecond, duration); } /** * @notice Allows the contract owner to flag profiles that misuse this action module. This serves as a first and/or * automated warning for `blacklistedProfiles` * @param profileId The profile id * @param toggle Toggle the flagged flag */ function flagProfile(uint256 profileId, bool toggle) external onlyOwner { flaggedProfiles[profileId] = toggle; emit ProfileFlagged(profileId, toggle, 0); } /** * @notice Allows the contract owner to blacklist profiles that misuse this action module. Profile must have been * flagged first. Blacklisted profiles cannot create or act. Reasons to blacklist include: * - those who delete publications (offchain) while an ad was active * - those who promote bad content * - those who cancel active ads without good reason * @param profileId The profile id * @param toggle Toggle the blacklist flag */ function blacklistProfile(uint256 profileId, bool toggle) external onlyOwner { if (toggle && !flaggedProfiles[profileId]) revert Unauthorized(); blacklistedProfiles[profileId] = toggle; emit ProfileBlacklisted(profileId, toggle); } /** * @dev Verify the init params; also make sure there is no active ad on a space owned by the profile */ function _verifyInitParams(uint256 profileId, address currency, uint256 costPerSecond, uint256 expireAt) internal { if (blacklistedProfiles[profileId]) revert Unauthorized(); uint256 activeSpaceId = activeSpaces[profileId].spaceId; ActiveAd memory activeAd = activeAds[profileId][activeSpaceId]; // cannot create while ad is active; profile owner can call `#cancelActiveAd` first if (_isValidExpiry(activeAd.expireAt)) revert NoInitDuringActiveAd(activeSpaceId); // no free ads and no expiring in the past if (costPerSecond == 0 || (expireAt != 0 && expireAt < block.timestamp)) revert InitParamsInvalid(); MODULE_REGISTRY.verifyErc20Currency(currency); } /** * @dev Must have already approved this contract as a delegated executor, for auto-mirror on "act" */ function _verifyDelegatedExecutor(uint256 profileId) internal view { if (!ILensProtocol(HUB).isDelegatedExecutorApproved(profileId, address(this))) revert OnlyWithDelegatedExecutor(); } /** * @dev On canceling an active ad, refund the advertiser whatever time they haven't paid for */ function _handleRefund(uint256 profileId, ActiveAd memory ad, address currency) internal returns (uint256 amount) { uint256 currentPaidAmount = (block.timestamp - ad.createdAt) * ad.costPerSecond; uint256 totalCost = (ad.expireAt - ad.createdAt) * ad.costPerSecond; amount = totalCost - currentPaidAmount; feesEarned[_owner(profileId)][currency] -= amount; IERC20(currency).safeTransfer(_owner(ad.advertiserId), amount); } /** * @dev On canceling an active ad, if due to a bad actor flag them for clients to consider + for potential blacklist */ function _handleFlaggedProfile( uint256 profileId, uint256 actorProfileId, CancelAdReason reason, ActiveAd memory ad ) internal { uint256 flaggedProfile; if (reason == CancelAdReason.BAD_ADVERTISER || reason == CancelAdReason.BAD_CONTENT) { flaggedProfile = ad.advertiserId; } else if (reason == CancelAdReason.BAD_ACTOR) { flaggedProfile = actorProfileId; } else if (block.timestamp < ad.createdAt + adMinDuration) { // if the space owner is canceling before the `adMinDuration`, flag them flaggedProfile = profileId; } if (flaggedProfile != 0) { flaggedProfiles[flaggedProfile] = true; emit ProfileFlagged(flaggedProfile, true, profileId); } } /** * @dev Calculate the cost for a new ad, taking into account any existing ad's bid and the protocol fee * NOTE: returned `costWithFee` is what we expect actors to approve() before calling act() */ function _getAdCost( bool activeAdExists, uint256 spaceCostPerSecond, uint256 activeAdCostPerSecond, uint256 duration ) internal view returns (uint256 cost, uint256 costWithFee, uint256 costPerSecond) { costPerSecond = activeAdExists ? activeAdCostPerSecond + (activeAdCostPerSecond * minBidIncreaseBps / BPS_MAX) : spaceCostPerSecond; cost = costPerSecond * duration; costWithFee = cost + (cost * protocolFeeBps / BPS_MAX); } /** * @dev Calculate and transfer client fee based on the `cost` */ function _transferClientFee( uint256 cost, uint16 clientFeePerActBps, address clientAddress, address currency ) internal returns (uint256 fee) { fee = cost * clientFeePerActBps / BPS_MAX; IERC20(currency).safeTransfer(clientAddress, fee); } /** * @dev Checks an active ad's expiry as existing and not in the past */ function _isValidExpiry(uint256 expireAt) internal view returns (bool) { return expireAt != 0 && expireAt > block.timestamp; } /** * @dev When renting a publication space, if the space allows an open action to be linked make sure that the open * action provided is enabled for the given ad's publication id */ function _validateOpenAction(bool allowOpenAction, uint256 actorProfileId, RentParams memory params) internal view { if (allowOpenAction && params.openActionModule != address(0) && !ILensProtocol(HUB).isActionModuleEnabledInPublication( actorProfileId, params.adPubId, params.openActionModule ) ) revert InvalidActionModuleForAd(params.openActionModule); } /** * @dev Validate whether the given `merkleProof` is in the tree for `merkleRoot` */ function _validateMerkleProof( bytes32 merkleRoot, uint256 profileId, uint256 index, bytes32[] memory merkleProof ) internal pure returns (bool) { return MerkleProof.verify(merkleProof, merkleRoot, keccak256(abi.encodePacked(profileId, index))); } /** * @dev Gets the profile owner */ function _owner(uint256 profileId) internal view returns (address) { return IERC721(HUB).ownerOf(profileId); } /** * @dev Tranfers the part of fee to referral(-s) and returns the total transferred * * @param processActionParams Parameters of the action * @param referralFee Creator-defined referral fee (bps) for the act * @param currency Currency used to pay for the ad space * @param amount Amount to take the referral fee from (after protocol/client fees) */ function _transferToReferrals( Types.ProcessActionParams calldata processActionParams, uint16 referralFee, address currency, uint256 amount ) internal returns (uint256) { uint256 totalReferralsAmount; if (referralFee != 0) { totalReferralsAmount = (amount * referralFee) / BPS_MAX; uint256 numberOfReferrals = processActionParams.referrerProfileIds.length; uint256 amountPerReferral = totalReferralsAmount / numberOfReferrals; if (amountPerReferral > 0) { uint256 i; while (i < numberOfReferrals) { IERC20(currency).safeTransfer( IERC721(HUB).ownerOf(processActionParams.referrerProfileIds[i]), amountPerReferral ); unchecked { ++i; } } } } return amount - totalReferralsAmount; } /** * @dev Upon successful act, this contract (as delegated executor) auto-mirrors the rentable post to re-surface it */ function _autoMirror(Types.ProcessActionParams calldata processActionParams) internal { uint256[] memory emptyArray = new uint256[](0); ILensProtocol(HUB).mirror(Types.MirrorParams({ profileId: processActionParams.publicationActedProfileId, metadataURI: "", pointedProfileId: processActionParams.publicationActedProfileId, pointedPubId: processActionParams.publicationActedId, referrerProfileIds: emptyArray, referrerPubIds: emptyArray, referenceModuleData: new bytes(0) })); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/draft-IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @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: MIT pragma solidity ^0.8.15; import {Errors} from 'lens/libraries/constants/Errors.sol'; /** * @title HubRestricted * @author Lens Protocol * * @notice This abstract contract adds a public `HUB` immutable field, as well as an `onlyHub` modifier, * to inherit from contracts that have functions restricted to be only called by the Lens hub. */ abstract contract HubRestricted { address public immutable HUB; modifier onlyHub() { if (msg.sender != HUB) { revert Errors.NotHub(); } _; } constructor(address hub) { HUB = hub; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0; /** * @title IERC721Burnable * @author Lens Protocol * * @notice Extension of ERC-721 including a function that allows the token to be burned. */ interface IERC721Burnable { /** * @notice Burns an NFT, removing it from circulation and essentially destroying it. * @custom:permission Owner of the NFT. * * @param tokenId The token ID of the token to burn. */ function burn(uint256 tokenId) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0; /** * @title IERC721MetaTx * @author Lens Protocol * * @notice Extension of ERC-721 including meta-tx signatures related functions. */ interface IERC721MetaTx { /** * @notice Returns the current signature nonce of the given signer. * * @param signer The address for which to query the nonce. * * @return uint256 The current nonce of the given signer. */ function nonces(address signer) external view returns (uint256); /** * @notice Returns the EIP-712 domain separator for this contract. * * @return bytes32 The domain separator. */ function getDomainSeparator() external view returns (bytes32); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0; import {Types} from 'lens/libraries/constants/Types.sol'; /** * @title IERC721Timestamped * @author Lens Protocol * * @notice Extension of ERC-721 including a struct for token data, which contains the owner and the mint timestamp, as * well as their associated getters. */ interface IERC721Timestamped { /** * @notice Returns the mint timestamp associated with a given NFT. * * @param tokenId The token ID of the NFT to query the mint timestamp for. * * @return uint256 Mint timestamp, this is stored as a uint96 but returned as a uint256 to reduce unnecessary * padding. */ function mintTimestampOf(uint256 tokenId) external view returns (uint256); /** * @notice Returns the token data associated with a given NFT. This allows fetching the token owner and * mint timestamp in a single call. * * @param tokenId The token ID of the NFT to query the token data for. * * @return TokenData A struct containing both the owner address and the mint timestamp. */ function tokenDataOf(uint256 tokenId) external view returns (Types.TokenData memory); /** * @notice Returns whether a token with the given token ID exists. * * @param tokenId The token ID of the NFT to check existence for. * * @return bool True if the token exists. */ function exists(uint256 tokenId) external view returns (bool); /** * @notice Returns the amount of tokens in circulation. * * @return uint256 The current total supply of tokens. */ function totalSupply() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0; import {IERC721} from '@openzeppelin/contracts/token/ERC721/IERC721.sol'; import {IERC721Timestamped} from 'lens/interfaces/IERC721Timestamped.sol'; import {IERC721Burnable} from 'lens/interfaces/IERC721Burnable.sol'; import {IERC721MetaTx} from 'lens/interfaces/IERC721MetaTx.sol'; import {IERC721Metadata} from '@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol'; interface ILensERC721 is IERC721, IERC721Timestamped, IERC721Burnable, IERC721MetaTx, IERC721Metadata {}
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0; import {Types} from 'lens/libraries/constants/Types.sol'; /** * @title ILensProtocol * @author Lens Protocol * * @notice This is the interface for Lens Protocol's core functions. It contains all the entry points for performing * social operations. */ interface ILensProtocol { /** * @notice Creates a profile with the specified parameters, minting a Profile NFT to the given recipient. * @custom:permissions Any whitelisted profile creator. * * @param createProfileParams A CreateProfileParams struct containing the needed params. */ function createProfile(Types.CreateProfileParams calldata createProfileParams) external returns (uint256); /** * @notice Sets the metadata URI for the given profile. * @custom:permissions Profile Owner or Delegated Executor. * * @param profileId The token ID of the profile to set the metadata URI for. * @param metadataURI The metadata URI to set for the given profile. */ function setProfileMetadataURI(uint256 profileId, string calldata metadataURI) external; /** * @custom:meta-tx setProfileMetadataURI. */ function setProfileMetadataURIWithSig( uint256 profileId, string calldata metadataURI, Types.EIP712Signature calldata signature ) external; /** * @notice Sets the follow module for the given profile. * @custom:permissions Profile Owner or Delegated Executor. * * @param profileId The token ID of the profile to set the follow module for. * @param followModule The follow module to set for the given profile, must be whitelisted. * @param followModuleInitData The data to be passed to the follow module for initialization. */ function setFollowModule(uint256 profileId, address followModule, bytes calldata followModuleInitData) external; /** * @custom:meta-tx setFollowModule. */ function setFollowModuleWithSig( uint256 profileId, address followModule, bytes calldata followModuleInitData, Types.EIP712Signature calldata signature ) external; /** * @notice Changes the delegated executors configuration for the given profile. It allows setting the approvals for * delegated executors in the specified configuration, as well as switching to it. * @custom:permissions Profile Owner. * * @param delegatorProfileId The ID of the profile to which the delegated executor is being changed for. * @param delegatedExecutors The array of delegated executors to set the approval for. * @param approvals The array of booleans indicating the corresponding executor's new approval status. * @param configNumber The number of the configuration where the executor approval state is being set. * @param switchToGivenConfig A boolean indicating if the configuration must be switched to the one with the given * number. */ function changeDelegatedExecutorsConfig( uint256 delegatorProfileId, address[] calldata delegatedExecutors, bool[] calldata approvals, uint64 configNumber, bool switchToGivenConfig ) external; /** * @notice Changes the delegated executors configuration for the given profile under the current configuration. * @custom:permissions Profile Owner. * * @param delegatorProfileId The ID of the profile to which the delegated executor is being changed for. * @param delegatedExecutors The array of delegated executors to set the approval for. * @param approvals The array of booleans indicating the corresponding executor's new approval status. */ function changeDelegatedExecutorsConfig( uint256 delegatorProfileId, address[] calldata delegatedExecutors, bool[] calldata approvals ) external; /** * @custom:meta-tx changeDelegatedExecutorsConfig. */ function changeDelegatedExecutorsConfigWithSig( uint256 delegatorProfileId, address[] calldata delegatedExecutors, bool[] calldata approvals, uint64 configNumber, bool switchToGivenConfig, Types.EIP712Signature calldata signature ) external; /** * @notice Publishes a post. * Post is the most basic publication type, and can be used to publish any kind of content. * Posts can have these types of modules initialized: * - Action modules: any number of publication actions (e.g. collect, tip, etc.) * - Reference module: a module handling the rules when referencing this post (e.g. token-gated comments) * @custom:permissions Profile Owner or Delegated Executor. * * @param postParams A PostParams struct containing the needed parameters. * * @return uint256 An integer representing the post's publication ID. */ function post(Types.PostParams calldata postParams) external returns (uint256); /** * @custom:meta-tx post. */ function postWithSig( Types.PostParams calldata postParams, Types.EIP712Signature calldata signature ) external returns (uint256); /** * @notice Publishes a comment on the given publication. * Comment is a type of reference publication that points to another publication. * Comments can have these types of modules initialized: * - Action modules: any number of publication actions (e.g. collect, tip, etc.) * - Reference module: a module handling the rules when referencing this comment (e.g. token-gated mirrors) * Comments can have referrers (e.g. publications or profiles that helped to discover the pointed publication). * @custom:permissions Profile Owner or Delegated Executor. * * @param commentParams A CommentParams struct containing the needed parameters. * * @return uint256 An integer representing the comment's publication ID. */ function comment(Types.CommentParams calldata commentParams) external returns (uint256); /** * @custom:meta-tx comment. */ function commentWithSig( Types.CommentParams calldata commentParams, Types.EIP712Signature calldata signature ) external returns (uint256); /** * @notice Publishes a mirror of the given publication. * Mirror is a type of reference publication that points to another publication but doesn't have content. * Mirrors don't have any modules initialized. * Mirrors can have referrers (e.g. publications or profiles that allowed to discover the pointed publication). * You cannot mirror a mirror, comment on a mirror, or quote a mirror. * @custom:permissions Profile Owner or Delegated Executor. * * @param mirrorParams A MirrorParams struct containing the necessary parameters. * * @return uint256 An integer representing the mirror's publication ID. */ function mirror(Types.MirrorParams calldata mirrorParams) external returns (uint256); /** * @custom:meta-tx mirror. */ function mirrorWithSig( Types.MirrorParams calldata mirrorParams, Types.EIP712Signature calldata signature ) external returns (uint256); /** * @notice Publishes a quote of the given publication. * Quote is a type of reference publication similar to mirror, but it has content and modules. * Quotes can have these types of modules initialized: * - Action modules: any number of publication actions (e.g. collect, tip, etc.) * - Reference module: a module handling the rules when referencing this quote (e.g. token-gated comments on quote) * Quotes can have referrers (e.g. publications or profiles that allowed to discover the pointed publication). * Unlike mirrors, you can mirror a quote, comment on a quote, or quote a quote. * @custom:permissions Profile Owner or Delegated Executor. * * @param quoteParams A QuoteParams struct containing the needed parameters. * * @return uint256 An integer representing the quote's publication ID. */ function quote(Types.QuoteParams calldata quoteParams) external returns (uint256); /** * @custom:meta-tx quote. */ function quoteWithSig( Types.QuoteParams calldata quoteParams, Types.EIP712Signature calldata signature ) external returns (uint256); /** * @notice Follows given profiles, executing each profile's follow module logic (if any). * @custom:permissions Profile Owner or Delegated Executor. * * @dev Both the `idsOfProfilesToFollow`, `followTokenIds`, and `datas` arrays must be of the same length, * regardless if the profiles do not have a follow module set. * * @param followerProfileId The ID of the profile the follows are being executed for. * @param idsOfProfilesToFollow The array of IDs of profiles to follow. * @param followTokenIds The array of follow token IDs to use for each follow (0 if you don't own a follow token). * @param datas The arbitrary data array to pass to the follow module for each profile if needed. * * @return uint256[] An array of follow token IDs representing the follow tokens created for each follow. */ function follow( uint256 followerProfileId, uint256[] calldata idsOfProfilesToFollow, uint256[] calldata followTokenIds, bytes[] calldata datas ) external returns (uint256[] memory); /** * @custom:meta-tx follow. */ function followWithSig( uint256 followerProfileId, uint256[] calldata idsOfProfilesToFollow, uint256[] calldata followTokenIds, bytes[] calldata datas, Types.EIP712Signature calldata signature ) external returns (uint256[] memory); /** * @notice Unfollows given profiles. * @custom:permissions Profile Owner or Delegated Executor. * * @param unfollowerProfileId The ID of the profile the unfollows are being executed for. * @param idsOfProfilesToUnfollow The array of IDs of profiles to unfollow. */ function unfollow(uint256 unfollowerProfileId, uint256[] calldata idsOfProfilesToUnfollow) external; /** * @custom:meta-tx unfollow. */ function unfollowWithSig( uint256 unfollowerProfileId, uint256[] calldata idsOfProfilesToUnfollow, Types.EIP712Signature calldata signature ) external; /** * @notice Sets the block status for the given profiles. Changing a profile's block status to `true` (i.e. blocked), * when will also force them to unfollow. * Blocked profiles cannot perform any actions with the profile that blocked them: they cannot comment or mirror * their publications, they cannot follow them, they cannot collect, tip them, etc. * @custom:permissions Profile Owner or Delegated Executor. * * @dev Both the `idsOfProfilesToSetBlockStatus` and `blockStatus` arrays must be of the same length. * * @param byProfileId The ID of the profile that is blocking/unblocking somebody. * @param idsOfProfilesToSetBlockStatus The array of IDs of profiles to set block status. * @param blockStatus The array of block statuses to use for each (true is blocked). */ function setBlockStatus( uint256 byProfileId, uint256[] calldata idsOfProfilesToSetBlockStatus, bool[] calldata blockStatus ) external; /** * @custom:meta-tx setBlockStatus. */ function setBlockStatusWithSig( uint256 byProfileId, uint256[] calldata idsOfProfilesToSetBlockStatus, bool[] calldata blockStatus, Types.EIP712Signature calldata signature ) external; /** * @notice Collects a given publication via signature with the specified parameters. * Collect can have referrers (e.g. publications or profiles that allowed to discover the pointed publication). * @custom:permissions Collector Profile Owner or its Delegated Executor. * @custom:pending-deprecation Collect modules were replaced by PublicationAction Collect modules in V2. This method * is left here for backwards compatibility with posts made in V1 that had Collect modules. * * @param collectParams A CollectParams struct containing the parameters. * * @return uint256 An integer representing the minted token ID. */ function collectLegacy(Types.LegacyCollectParams calldata collectParams) external returns (uint256); /** * @custom:meta-tx collect. * @custom:pending-deprecation */ function collectLegacyWithSig( Types.LegacyCollectParams calldata collectParams, Types.EIP712Signature calldata signature ) external returns (uint256); /** * @notice Acts on a given publication with the specified parameters. * You can act on a publication except a mirror (if it has at least one action module initialized). * Actions can have referrers (e.g. publications or profiles that allowed to discover the pointed publication). * @custom:permissions Actor Profile Owner or its Delegated Executor. * * @param publicationActionParams A PublicationActionParams struct containing the parameters. * * @return bytes Arbitrary data the action module returns. */ function act(Types.PublicationActionParams calldata publicationActionParams) external returns (bytes memory); /** * @custom:meta-tx act. */ function actWithSig( Types.PublicationActionParams calldata publicationActionParams, Types.EIP712Signature calldata signature ) external returns (bytes memory); /** * @dev This function is used to invalidate signatures by incrementing the nonce of the signer. * @param increment The amount to increment the nonce by (max 255). */ function incrementNonce(uint8 increment) external; ///////////////////////////////// /// VIEW FUNCTIONS /// ///////////////////////////////// /** * @notice Returns whether or not `followerProfileId` is following `followedProfileId`. * * @param followerProfileId The ID of the profile whose following state should be queried. * @param followedProfileId The ID of the profile whose followed state should be queried. * * @return bool True if `followerProfileId` is following `followedProfileId`, false otherwise. */ function isFollowing(uint256 followerProfileId, uint256 followedProfileId) external view returns (bool); /** * @notice Returns whether the given address is approved as delegated executor, in the configuration with the given * number, to act on behalf of the given profile. * * @param delegatorProfileId The ID of the profile to check the delegated executor approval for. * @param delegatedExecutor The address to query the delegated executor approval for. * @param configNumber The number of the configuration where the executor approval state is being queried. * * @return bool True if the address is approved as a delegated executor to act on behalf of the profile in the * given configuration, false otherwise. */ function isDelegatedExecutorApproved( uint256 delegatorProfileId, address delegatedExecutor, uint64 configNumber ) external view returns (bool); /** * @notice Returns whether the given address is approved as delegated executor, in the current configuration, to act * on behalf of the given profile. * * @param delegatorProfileId The ID of the profile to check the delegated executor approval for. * @param delegatedExecutor The address to query the delegated executor approval for. * * @return bool True if the address is approved as a delegated executor to act on behalf of the profile in the * current configuration, false otherwise. */ function isDelegatedExecutorApproved( uint256 delegatorProfileId, address delegatedExecutor ) external view returns (bool); /** * @notice Returns the current delegated executor config number for the given profile. * * @param delegatorProfileId The ID of the profile from which the delegated executors config number is being queried * * @return uint256 The current delegated executor configuration number. */ function getDelegatedExecutorsConfigNumber(uint256 delegatorProfileId) external view returns (uint64); /** * @notice Returns the previous used delegated executor config number for the given profile. * * @param delegatorProfileId The ID of the profile from which the delegated executors' previous configuration number * set is being queried. * * @return uint256 The delegated executor configuration number previously set. It will coincide with the current * configuration set if it was never switched from the default one. */ function getDelegatedExecutorsPrevConfigNumber(uint256 delegatorProfileId) external view returns (uint64); /** * @notice Returns the maximum delegated executor config number for the given profile. * This is the maximum config number that was ever used by this profile. * When creating a new clean configuration, you can only use a number that is maxConfigNumber + 1. * * @param delegatorProfileId The ID of the profile from which the delegated executors' maximum configuration number * set is being queried. * * @return uint256 The delegated executor maximum configuration number set. */ function getDelegatedExecutorsMaxConfigNumberSet(uint256 delegatorProfileId) external view returns (uint64); /** * @notice Returns whether `profileId` is blocked by `byProfileId`. * See setBlockStatus() for more information on how blocking works on the platform. * * @param profileId The ID of the profile whose blocked status should be queried. * @param byProfileId The ID of the profile whose blocker status should be queried. * * @return bool True if `profileId` is blocked by `byProfileId`, false otherwise. */ function isBlocked(uint256 profileId, uint256 byProfileId) external view returns (bool); /** * @notice Returns the URI associated with a given publication. * This is used to store the publication's metadata, e.g.: content, images, etc. * * @param profileId The token ID of the profile that published the publication to query. * @param pubId The publication ID of the publication to query. * * @return string The URI associated with a given publication. */ function getContentURI(uint256 profileId, uint256 pubId) external view returns (string memory); /** * @notice Returns the full profile struct associated with a given profile token ID. * * @param profileId The token ID of the profile to query. * * @return Profile The profile struct of the given profile. */ function getProfile(uint256 profileId) external view returns (Types.Profile memory); /** * @notice Returns the full publication struct for a given publication. * * @param profileId The token ID of the profile that published the publication to query. * @param pubId The publication ID of the publication to query. * * @return Publication The publication struct associated with the queried publication. */ function getPublication(uint256 profileId, uint256 pubId) external view returns (Types.PublicationMemory memory); /** * @notice Returns the type of a given publication. * The type can be one of the following (see PublicationType enum): * - Nonexistent * - Post * - Comment * - Mirror * - Quote * * @param profileId The token ID of the profile that published the publication to query. * @param pubId The publication ID of the publication to query. * * @return PublicationType The publication type of the queried publication. */ function getPublicationType(uint256 profileId, uint256 pubId) external view returns (Types.PublicationType); /** * @notice Returns wether a given Action Module is enabled for a given publication. * * @param profileId The token ID of the profile that published the publication to query. * @param pubId The publication ID of the publication to query. * @param module The address of the Action Module to query. * * @return bool True if the Action Module is enabled for the queried publication, false if not. */ function isActionModuleEnabledInPublication( uint256 profileId, uint256 pubId, address module ) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.15; interface IModuleRegistry { enum ModuleType { __, // Just to avoid 0 as valid ModuleType PUBLICATION_ACTION_MODULE, REFERENCE_MODULE, FOLLOW_MODULE } // Modules functions function verifyModule(address moduleAddress, uint256 moduleType) external returns (bool); function registerModule(address moduleAddress, uint256 moduleType) external returns (bool); function getModuleTypes(address moduleAddress) external view returns (uint256); function isModuleRegistered(address moduleAddress) external view returns (bool); function isModuleRegisteredAs(address moduleAddress, uint256 moduleType) external view returns (bool); // Currencies functions function verifyErc20Currency(address currencyAddress) external returns (bool); function registerErc20Currency(address currencyAddress) external returns (bool); function isErc20CurrencyRegistered(address currencyAddress) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0; import {Types} from 'lens/libraries/constants/Types.sol'; /** * @title IPublicationAction * @author Lens Protocol * * @notice This is the standard interface for all Lens-compatible Publication Actions. * Publication action modules allow users to execute actions directly from a publication, like: * - Minting NFTs. * - Collecting a publication. * - Sending funds to the publication author (e.g. tipping). * - Etc. * Referrers are supported, so any publication or profile that references the publication can receive a share from the * publication's action if the action module supports it. */ interface IPublicationActionModule { /** * @notice Initializes the action module for the given publication being published with this Action module. * @custom:permissions LensHub. * * @param profileId The profile ID of the author publishing the content with this Publication Action. * @param pubId The publication ID being published. * @param transactionExecutor The address of the transaction executor (e.g. for any funds to transferFrom). * @param data Arbitrary data passed from the user to be decoded by the Action Module during initialization. * * @return bytes Any custom ABI-encoded data. This will be a LensHub event params that can be used by * indexers or UIs. */ function initializePublicationAction( uint256 profileId, uint256 pubId, address transactionExecutor, bytes calldata data ) external returns (bytes memory); /** * @notice Processes the action for a given publication. This includes the action's logic and any monetary/token * operations. * @custom:permissions LensHub. * * @param processActionParams The parameters needed to execute the publication action. * * @return bytes Any custom ABI-encoded data. This will be a LensHub event params that can be used by * indexers or UIs. */ function processPublicationAction(Types.ProcessActionParams calldata processActionParams) external returns (bytes memory); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0; library Errors { error CannotInitImplementation(); error Initialized(); error SignatureExpired(); error SignatureInvalid(); error InvalidOwner(); error NotOwnerOrApproved(); error NotHub(); error TokenDoesNotExist(); error NotGovernance(); error NotGovernanceOrEmergencyAdmin(); error EmergencyAdminCanOnlyPauseFurther(); error NotProfileOwner(); error PublicationDoesNotExist(); error CallerNotFollowNFT(); error CallerNotCollectNFT(); // Legacy error ArrayMismatch(); error NotWhitelisted(); error NotRegistered(); error InvalidParameter(); error ExecutorInvalid(); error Blocked(); error SelfBlock(); error NotFollowing(); error SelfFollow(); error InvalidReferrer(); error InvalidPointedPub(); error NonERC721ReceiverImplementer(); error AlreadyEnabled(); // Module Errors error InitParamsInvalid(); error ActionNotAllowed(); error CollectNotAllowed(); // Used in LegacyCollectLib (pending deprecation) // MultiState Errors error Paused(); error PublishingPaused(); // Profile Guardian Errors error GuardianEnabled(); error NotEOA(); error DisablingAlreadyTriggered(); // Migration Errors error NotMigrationAdmin(); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0; /** * @title Types * @author Lens Protocol * * @notice A standard library of data types used throughout the Lens Protocol. */ library Types { /** * @notice ERC721Timestamped storage. Contains the owner address and the mint timestamp for every NFT. * * Note: Instead of the owner address in the _tokenOwners private mapping, we now store it in the * _tokenData mapping, alongside the mint timestamp. * * @param owner The token owner. * @param mintTimestamp The mint timestamp. */ struct TokenData { address owner; uint96 mintTimestamp; } /** * @notice A struct containing token follow-related data. * * @param followerProfileId The ID of the profile using the token to follow. * @param originalFollowTimestamp The timestamp of the first follow performed with the token. * @param followTimestamp The timestamp of the current follow, if a profile is using the token to follow. * @param profileIdAllowedToRecover The ID of the profile allowed to recover the follow ID, if any. */ struct FollowData { uint160 followerProfileId; uint48 originalFollowTimestamp; uint48 followTimestamp; uint256 profileIdAllowedToRecover; } /** * @notice An enum containing the different states the protocol can be in, limiting certain actions. * * @param Unpaused The fully unpaused state. * @param PublishingPaused The state where only publication creation functions are paused. * @param Paused The fully paused state. */ enum ProtocolState { Unpaused, PublishingPaused, Paused } /** * @notice An enum specifically used in a helper function to easily retrieve the publication type for integrations. * * @param Nonexistent An indicator showing the queried publication does not exist. * @param Post A standard post, having an URI, action modules and no pointer to another publication. * @param Comment A comment, having an URI, action modules and a pointer to another publication. * @param Mirror A mirror, having a pointer to another publication, but no URI or action modules. * @param Quote A quote, having an URI, action modules, and a pointer to another publication. */ enum PublicationType { Nonexistent, Post, Comment, Mirror, Quote } /** * @notice A struct containing the necessary information to reconstruct an EIP-712 typed data signature. * * @param signer The address of the signer. Specially needed as a parameter to support EIP-1271. * @param v The signature's recovery parameter. * @param r The signature's r parameter. * @param s The signature's s parameter. * @param deadline The signature's deadline. */ struct EIP712Signature { address signer; uint8 v; bytes32 r; bytes32 s; uint256 deadline; } /** * @notice A struct containing profile data. * * @param pubCount The number of publications made to this profile. * @param followModule The address of the current follow module in use by this profile, can be address(0) in none. * @param followNFT The address of the followNFT associated with this profile. It can be address(0) if the * profile has not been followed yet, as the collection is lazy-deployed upon the first follow. * @param __DEPRECATED__handle DEPRECATED in V2: handle slot, was replaced with LensHandles. * @param __DEPRECATED__imageURI DEPRECATED in V2: The URI to be used for the profile image. * @param __DEPRECATED__followNFTURI DEPRECATED in V2: The URI used for the follow NFT image. * @param metadataURI MetadataURI is used to store the profile's metadata, for example: displayed name, description, * interests, etc. */ struct Profile { uint256 pubCount; // offset 0 address followModule; // offset 1 address followNFT; // offset 2 string __DEPRECATED__handle; // offset 3 string __DEPRECATED__imageURI; // offset 4 string __DEPRECATED__followNFTURI; // Deprecated in V2 as we have a common tokenURI for all Follows, offset 5 string metadataURI; // offset 6 } /** * @notice A struct containing publication data. * * @param pointedProfileId The profile token ID to point the publication to. * @param pointedPubId The publication ID to point the publication to. * These are used to implement the "reference" feature of the platform and is used in: * - Mirrors * - Comments * - Quotes * There are (0,0) if the publication is not pointing to any other publication (i.e. the publication is a Post). * @param contentURI The URI to set for the content of publication (can be ipfs, arweave, http, etc). * @param referenceModule Reference module associated with this profile, if any. * @param __DEPRECATED__collectModule Collect module associated with this publication, if any. Deprecated in V2. * @param __DEPRECATED__collectNFT Collect NFT associated with this publication, if any. Deprecated in V2. * @param pubType The type of publication, can be Nonexistent, Post, Comment, Mirror or Quote. * @param rootProfileId The profile ID of the root post (to determine if comments/quotes and mirrors come from it). * Posts, V1 publications and publications rooted in V1 publications don't have it set. * @param rootPubId The publication ID of the root post (to determine if comments/quotes and mirrors come from it). * Posts, V1 publications and publications rooted in V1 publications don't have it set. * @param actionModuleEnabled The action modules enabled in a given publication. */ struct Publication { uint256 pointedProfileId; uint256 pointedPubId; string contentURI; address referenceModule; address __DEPRECATED__collectModule; // Deprecated in V2 address __DEPRECATED__collectNFT; // Deprecated in V2 // Added in Lens V2, so these will be zero for old publications: PublicationType pubType; uint256 rootProfileId; uint256 rootPubId; mapping(address => bool) actionModuleEnabled; } struct PublicationMemory { uint256 pointedProfileId; uint256 pointedPubId; string contentURI; address referenceModule; address __DEPRECATED__collectModule; // Deprecated in V2 address __DEPRECATED__collectNFT; // Deprecated in V2 // Added in Lens V2, so these will be zero for old publications: PublicationType pubType; uint256 rootProfileId; uint256 rootPubId; // bytes32 __ACTION_MODULE_ENABLED_MAPPING; // Mappings are not supported in memory. } /** * @notice A struct containing the parameters required for the `createProfile()` function. * * @param to The address receiving the profile. * @param followModule The follow module to use, can be the zero address. * @param followModuleInitData The follow module initialization data, if any. */ struct CreateProfileParams { address to; address followModule; bytes followModuleInitData; } /** * @notice A struct containing the parameters required for the `post()` function. * * @param profileId The token ID of the profile to publish to. * @param contentURI The URI to set for this new publication. * @param actionModules The action modules to set for this new publication. * @param actionModulesInitDatas The data to pass to the action modules' initialization. * @param referenceModule The reference module to set for the given publication, must be whitelisted. * @param referenceModuleInitData The data to be passed to the reference module for initialization. */ struct PostParams { uint256 profileId; string contentURI; address[] actionModules; bytes[] actionModulesInitDatas; address referenceModule; bytes referenceModuleInitData; } /** * @notice A struct containing the parameters required for the `comment()` function. * * @param profileId The token ID of the profile to publish to. * @param contentURI The URI to set for this new publication. * @param pointedProfileId The profile token ID to point the comment to. * @param pointedPubId The publication ID to point the comment to. * @param referrerProfileId The profile token ID of the publication that referred to the publication being commented on/quoted. * @param referrerPubId The ID of the publication that referred to the publication being commented on/quoted. * @param referenceModuleData The data passed to the reference module. * @param actionModules The action modules to set for this new publication. * @param actionModulesInitDatas The data to pass to the action modules' initialization. * @param referenceModule The reference module to set for the given publication, must be whitelisted. * @param referenceModuleInitData The data to be passed to the reference module for initialization. */ struct CommentParams { uint256 profileId; string contentURI; uint256 pointedProfileId; uint256 pointedPubId; uint256[] referrerProfileIds; uint256[] referrerPubIds; bytes referenceModuleData; address[] actionModules; bytes[] actionModulesInitDatas; address referenceModule; bytes referenceModuleInitData; } /** * @notice A struct containing the parameters required for the `quote()` function. * * @param profileId The token ID of the profile to publish to. * @param contentURI The URI to set for this new publication. * @param pointedProfileId The profile token ID of the publication author that is quoted. * @param pointedPubId The publication ID that is quoted. * @param referrerProfileId The profile token ID of the publication that referred to the publication being commented on/quoted. * @param referrerPubId The ID of the publication that referred to the publication being commented on/quoted. * @param referenceModuleData The data passed to the reference module. * @param actionModules The action modules to set for this new publication. * @param actionModulesInitDatas The data to pass to the action modules' initialization. * @param referenceModule The reference module to set for the given publication, must be whitelisted. * @param referenceModuleInitData The data to be passed to the reference module for initialization. */ struct QuoteParams { uint256 profileId; string contentURI; uint256 pointedProfileId; uint256 pointedPubId; uint256[] referrerProfileIds; uint256[] referrerPubIds; bytes referenceModuleData; address[] actionModules; bytes[] actionModulesInitDatas; address referenceModule; bytes referenceModuleInitData; } /** * @notice A struct containing the parameters required for the `comment()` or `quote()` internal functions. * * @param profileId The token ID of the profile to publish to. * @param contentURI The URI to set for this new publication. * @param pointedProfileId The profile token ID of the publication author that is commented on/quoted. * @param pointedPubId The publication ID that is commented on/quoted. * @param referrerProfileId The profile token ID of the publication that referred to the publication being commented on/quoted. * @param referrerPubId The ID of the publication that referred to the publication being commented on/quoted. * @param referenceModuleData The data passed to the reference module. * @param actionModules The action modules to set for this new publication. * @param actionModulesInitDatas The data to pass to the action modules' initialization. * @param referenceModule The reference module to set for the given publication, must be whitelisted. * @param referenceModuleInitData The data to be passed to the reference module for initialization. */ struct ReferencePubParams { uint256 profileId; string contentURI; uint256 pointedProfileId; uint256 pointedPubId; uint256[] referrerProfileIds; uint256[] referrerPubIds; bytes referenceModuleData; address[] actionModules; bytes[] actionModulesInitDatas; address referenceModule; bytes referenceModuleInitData; } /** * @notice A struct containing the parameters required for the `mirror()` function. * * @param profileId The token ID of the profile to publish to. * @param metadataURI the URI containing metadata attributes to attach to this mirror publication. * @param pointedProfileId The profile token ID to point the mirror to. * @param pointedPubId The publication ID to point the mirror to. * @param referenceModuleData The data passed to the reference module. */ struct MirrorParams { uint256 profileId; string metadataURI; uint256 pointedProfileId; uint256 pointedPubId; uint256[] referrerProfileIds; uint256[] referrerPubIds; bytes referenceModuleData; } /** * Deprecated in V2: Will be removed after some time after upgrading to V2. * @notice A struct containing the parameters required for the legacy `collect()` function. * @dev The referrer can only be a mirror of the publication being collected. * * @param publicationCollectedProfileId The token ID of the profile that published the publication to collect. * @param publicationCollectedId The publication to collect's publication ID. * @param collectorProfileId The collector profile. * @param referrerProfileId The ID of a profile that authored a mirror that helped discovering the collected pub. * @param referrerPubId The ID of the mirror that helped discovering the collected pub. * @param collectModuleData The arbitrary data to pass to the collectModule if needed. */ struct LegacyCollectParams { uint256 publicationCollectedProfileId; uint256 publicationCollectedId; uint256 collectorProfileId; uint256 referrerProfileId; uint256 referrerPubId; bytes collectModuleData; } /** * @notice A struct containing the parameters required for the `action()` function. * * @param publicationActedProfileId The token ID of the profile that published the publication to action. * @param publicationActedId The publication to action's publication ID. * @param actorProfileId The actor profile. * @param referrerProfileId * @param referrerPubId * @param actionModuleAddress * @param actionModuleData The arbitrary data to pass to the actionModule if needed. */ struct PublicationActionParams { uint256 publicationActedProfileId; uint256 publicationActedId; uint256 actorProfileId; uint256[] referrerProfileIds; uint256[] referrerPubIds; address actionModuleAddress; bytes actionModuleData; } struct ProcessActionParams { uint256 publicationActedProfileId; uint256 publicationActedId; uint256 actorProfileId; address actorProfileOwner; address transactionExecutor; uint256[] referrerProfileIds; uint256[] referrerPubIds; Types.PublicationType[] referrerPubTypes; bytes actionModuleData; } struct ProcessCommentParams { uint256 profileId; uint256 pubId; address transactionExecutor; uint256 pointedProfileId; uint256 pointedPubId; uint256[] referrerProfileIds; uint256[] referrerPubIds; Types.PublicationType[] referrerPubTypes; bytes data; } struct ProcessQuoteParams { uint256 profileId; uint256 pubId; address transactionExecutor; uint256 pointedProfileId; uint256 pointedPubId; uint256[] referrerProfileIds; uint256[] referrerPubIds; Types.PublicationType[] referrerPubTypes; bytes data; } struct ProcessMirrorParams { uint256 profileId; uint256 pubId; address transactionExecutor; uint256 pointedProfileId; uint256 pointedPubId; uint256[] referrerProfileIds; uint256[] referrerPubIds; Types.PublicationType[] referrerPubTypes; bytes data; } /** * @notice A struct containing a profile's delegated executors configuration. * * @param isApproved Tells when an address is approved as delegated executor in the given configuration number. * @param configNumber Current configuration number in use. * @param prevConfigNumber Previous configuration number set, before switching to the current one. * @param maxConfigNumberSet Maximum configuration number ever used. */ struct DelegatedExecutorsConfig { mapping(uint256 => mapping(address => bool)) isApproved; // isApproved[configNumber][delegatedExecutor] uint64 configNumber; uint64 prevConfigNumber; uint64 maxConfigNumberSet; } struct TreasuryData { address treasury; uint16 treasuryFeeBPS; } struct MigrationParams { address lensHandlesAddress; address tokenHandleRegistryAddress; address legacyFeeFollowModule; address legacyProfileFollowModule; address newFeeFollowModule; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0; import {IERC165} from '@openzeppelin/contracts/utils/introspection/IERC165.sol'; interface ILensModule is IERC165 { /// @dev for now we check for keccak('LENS_MODULE'); /// Override this and add the type(IModuleInterface).interfaceId for corresponding module type function supportsInterface(bytes4 interfaceID) external view returns (bool); /// @notice Human-readable description of the module // Can be JSON // Can be contract source code // Can be github link // Can be ipfs with documentation // etc function getModuleMetadataURI() external view returns (string memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; import {ILensModule} from 'lens/modules/interfaces/ILensModule.sol'; abstract contract LensModule is ILensModule { /// @inheritdoc ILensModule function supportsInterface(bytes4 interfaceID) public pure virtual override returns (bool) { return interfaceID == bytes4(keccak256(abi.encodePacked('LENS_MODULE'))); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; import {Ownable} from '@openzeppelin/contracts/access/Ownable.sol'; import {LensModule} from 'lens/modules/LensModule.sol'; contract LensModuleMetadata is LensModule, Ownable { string public metadataURI; constructor(address owner_) Ownable() { _transferOwnership(owner_); } function setModuleMetadataURI(string memory _metadataURI) external onlyOwner { metadataURI = _metadataURI; } function getModuleMetadataURI() external view returns (string memory) { return metadataURI; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; import {LensModuleMetadata} from 'lens/modules/LensModuleMetadata.sol'; contract LensModuleMetadataInitializable is LensModuleMetadata { constructor(address owner_) LensModuleMetadata(owner_) {} function initialize(address moduleOwner) external virtual { if (owner() != address(0) || moduleOwner == address(0)) { revert(); } _transferOwnership(moduleOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol) pragma solidity ^0.8.0; /** * @dev These functions deal with verification of Merkle Tree proofs. * * The tree and the proofs can be generated using our * https://github.com/OpenZeppelin/merkle-tree[JavaScript library]. * You will find a quickstart guide in the readme. * * WARNING: You should avoid using leaf values that are 64 bytes long prior to * hashing, or use a hash function other than keccak256 for hashing leaves. * This is because the concatenation of a sorted pair of internal nodes in * the merkle tree could be reinterpreted as a leaf value. * OpenZeppelin's JavaScript library generates merkle trees that are safe * against this attack out of the box. */ library MerkleProof { /** * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree * defined by `root`. For this, a `proof` must be provided, containing * sibling hashes on the branch from the leaf to the root of the tree. Each * pair of leaves and each pair of pre-images are assumed to be sorted. */ function verify( bytes32[] memory proof, bytes32 root, bytes32 leaf ) internal pure returns (bool) { return processProof(proof, leaf) == root; } /** * @dev Calldata version of {verify} * * _Available since v4.7._ */ function verifyCalldata( bytes32[] calldata proof, bytes32 root, bytes32 leaf ) internal pure returns (bool) { return processProofCalldata(proof, leaf) == root; } /** * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt * hash matches the root of the tree. When processing the proof, the pairs * of leafs & pre-images are assumed to be sorted. * * _Available since v4.4._ */ function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Calldata version of {processProof} * * _Available since v4.7._ */ function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}. * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function multiProofVerify( bytes32[] memory proof, bool[] memory proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProof(proof, proofFlags, leaves) == root; } /** * @dev Calldata version of {multiProofVerify} * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function multiProofVerifyCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProofCalldata(proof, proofFlags, leaves) == root; } /** * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false * respectively. * * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer). * * _Available since v4.7._ */ function processMultiProof( bytes32[] memory proof, bool[] memory proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the merkle tree. uint256 leavesLen = leaves.length; uint256 totalHashes = proofFlags.length; // Check proof validity. require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof"); // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value for the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { return hashes[totalHashes - 1]; } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } /** * @dev Calldata version of {processMultiProof}. * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function processMultiProofCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the merkle tree. uint256 leavesLen = leaves.length; uint256 totalHashes = proofFlags.length; // Check proof validity. require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof"); // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value for the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { return hashes[totalHashes - 1]; } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) { return a < b ? _efficientHash(a, b) : _efficientHash(b, a); } function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) { /// @solidity memory-safe-assembly assembly { mstore(0x00, a) mstore(0x20, b) value := keccak256(0x00, 0x40) } } }
// SPDX-License-Identifier: MIT /* __/\\\\____________/\\\\_____/\\\\\\\\\_____/\\\\\\\\\\\\_____/\\\\\\\\\\\\\\\__/\\\\\\\\\\\_ _\/\\\\\\________/\\\\\\___/\\\\\\\\\\\\\__\/\\\////////\\\__\/\\\///////////__\/////\\\///__ _\/\\\//\\\____/\\\//\\\__/\\\/////////\\\_\/\\\______\//\\\_\/\\\_________________\/\\\_____ _\/\\\\///\\\/\\\/_\/\\\_\/\\\_______\/\\\_\/\\\_______\/\\\_\/\\\\\\\\\\\_________\/\\\_____ _\/\\\__\///\\\/___\/\\\_\/\\\\\\\\\\\\\\\_\/\\\_______\/\\\_\/\\\///////__________\/\\\_____ _\/\\\____\///_____\/\\\_\/\\\/////////\\\_\/\\\_______\/\\\_\/\\\_________________\/\\\_____ _\/\\\_____________\/\\\_\/\\\_______\/\\\_\/\\\_______/\\\__\/\\\_________________\/\\\_____ _\/\\\_____________\/\\\_\/\\\_______\/\\\_\/\\\\\\\\\\\\/___\/\\\______________/\\\\\\\\\\\_ _\///______________\///__\///________\///__\////////////_____\///______________\///////////__ */ pragma solidity ^0.8.21; interface IRentableSpaceAction { enum CancelAdReason { BAD_CONTENT, BAD_ADVERTISER, BAD_ACTOR, // any bad activity EXIT, // to allow good faith canceling after `adMinDuration` OTHER } struct ActiveSpace { uint256 spaceId; // the pub id initialized with this action module address currency; // accepted currency uint256 costPerSecond; // cost per second to rent the pub space (in wei) uint256 expireAt; // how long the pub space is active for (0 for no expiry) bytes32 interestMerkleRoot; // [optional] require advertisers to fit this interest category bool allowOpenAction; // allow advertisers to link their publication's open action as part of the ad uint16 clientFeePerActBps; // give clients a % of rented space fees, after protocol fee uint16 referralFeePerActBps; // give referrer profiles a % of rented space fees, after protocol/client fees } struct ActiveAd { uint256 advertiserId; // the profile of the advertiser uint256 adId; // [optional] the pub id to replace the space - the ad uint256 createdAt; // to calculate total cost uint256 expireAt; // renter paid up until this timestamp uint256 costPerSecond; // allow profiles to bid higher than this to replace the ad address openActionModule; // [optional] the linked open action module string adContentUri; // [optional] if no pub id, use this lens metadata content uri as the ad } struct RentParams { uint256 adPubId; // [optional] the pub id to pull contentUri and action module for the ad uint256 duration; // the amount of time the advertiser wishes to pay for (in seconds) uint256 costPerSecond; // the amount the advertisers is willing to pay per second uint256 merkleProofIndex; // [optional] proof index the space's category merkle address clientAddress; // [optional] the whitelisted client address to receive fees address openActionModule; // [optional] the linked open action module string adContentUri; // [optional] if no pub id passed in, use this lens metadata uri bytes32[] merkleProof; // [optional] proof for the space's category merkle } error InitParamsInvalid(); error NoZeroAddress(); error Unauthorized(); error NotFoundOrExpired(); error NoInitDuringActiveAd(uint256 activeSpaceId); error InvalidActionModuleForAd(address openAction); error MustCancelActiveAd(uint256 activeSpaceId); error NoFeesEarned(); error OnlyWithDelegatedExecutor(); event InitAction(uint256 profileId, uint256 pubId, uint256 costPerSecond); event SetActiveAd(uint256 profileId, uint256 pubId, uint256 advertiserId, uint256 adId, string contentUri); event CancelActiveAd(uint256 profileId, uint256 pubId, uint256 adPubId, CancelAdReason reason, string otherReason, uint256 refundAmount, bool closeActiveSpace); event ProfileFlagged(uint256 profileId, bool isFlagged, uint256 byProfile); event ProfileBlacklisted(uint256 profileId, bool isBlacklisted); }
{ "viaIR": true, "optimizer": { "enabled": true, "runs": 2000 }, "evmVersion": "london", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"hub","type":"address"},{"internalType":"address","name":"_moduleRegistry","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InitParamsInvalid","type":"error"},{"inputs":[{"internalType":"address","name":"openAction","type":"address"}],"name":"InvalidActionModuleForAd","type":"error"},{"inputs":[{"internalType":"uint256","name":"activeSpaceId","type":"uint256"}],"name":"MustCancelActiveAd","type":"error"},{"inputs":[],"name":"NoFeesEarned","type":"error"},{"inputs":[{"internalType":"uint256","name":"activeSpaceId","type":"uint256"}],"name":"NoInitDuringActiveAd","type":"error"},{"inputs":[],"name":"NoZeroAddress","type":"error"},{"inputs":[],"name":"NotFoundOrExpired","type":"error"},{"inputs":[],"name":"NotHub","type":"error"},{"inputs":[],"name":"OnlyWithDelegatedExecutor","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"profileId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"pubId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"adPubId","type":"uint256"},{"indexed":false,"internalType":"enum IRentableSpaceAction.CancelAdReason","name":"reason","type":"uint8"},{"indexed":false,"internalType":"string","name":"otherReason","type":"string"},{"indexed":false,"internalType":"uint256","name":"refundAmount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"closeActiveSpace","type":"bool"}],"name":"CancelActiveAd","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"profileId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"pubId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"costPerSecond","type":"uint256"}],"name":"InitAction","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"profileId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isBlacklisted","type":"bool"}],"name":"ProfileBlacklisted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"profileId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isFlagged","type":"bool"},{"indexed":false,"internalType":"uint256","name":"byProfile","type":"uint256"}],"name":"ProfileFlagged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"profileId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"pubId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"advertiserId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"adId","type":"uint256"},{"indexed":false,"internalType":"string","name":"contentUri","type":"string"}],"name":"SetActiveAd","type":"event"},{"inputs":[],"name":"HUB","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MODULE_REGISTRY","outputs":[{"internalType":"contract IModuleRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"uint256","name":"spaceId","type":"uint256"}],"name":"activeAds","outputs":[{"internalType":"uint256","name":"advertiserId","type":"uint256"},{"internalType":"uint256","name":"adId","type":"uint256"},{"internalType":"uint256","name":"createdAt","type":"uint256"},{"internalType":"uint256","name":"expireAt","type":"uint256"},{"internalType":"uint256","name":"costPerSecond","type":"uint256"},{"internalType":"address","name":"openActionModule","type":"address"},{"internalType":"string","name":"adContentUri","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"}],"name":"activeSpaces","outputs":[{"internalType":"uint256","name":"spaceId","type":"uint256"},{"internalType":"address","name":"currency","type":"address"},{"internalType":"uint256","name":"costPerSecond","type":"uint256"},{"internalType":"uint256","name":"expireAt","type":"uint256"},{"internalType":"bytes32","name":"interestMerkleRoot","type":"bytes32"},{"internalType":"bool","name":"allowOpenAction","type":"bool"},{"internalType":"uint16","name":"clientFeePerActBps","type":"uint16"},{"internalType":"uint16","name":"referralFeePerActBps","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"adMinDuration","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"bool","name":"toggle","type":"bool"}],"name":"blacklistProfile","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"}],"name":"blacklistedProfiles","outputs":[{"internalType":"bool","name":"blacklisted","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"uint256","name":"actorProfileId","type":"uint256"},{"internalType":"enum IRentableSpaceAction.CancelAdReason","name":"reason","type":"uint8"},{"internalType":"string","name":"otherReason","type":"string"},{"internalType":"bool","name":"closeSpace","type":"bool"}],"name":"cancelActiveAd","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"}],"name":"closeActiveSpace","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"currency","type":"address"}],"name":"feesEarned","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"bool","name":"toggle","type":"bool"}],"name":"flagProfile","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"}],"name":"flaggedProfiles","outputs":[{"internalType":"bool","name":"flagged","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"uint256","name":"pubId","type":"uint256"}],"name":"getActiveAd","outputs":[{"internalType":"string","name":"contentUri","type":"string"},{"internalType":"uint256","name":"adProfileId","type":"uint256"},{"internalType":"uint256","name":"adPubId","type":"uint256"},{"internalType":"address","name":"openActionModule","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"uint256","name":"duration","type":"uint256"}],"name":"getAdCost","outputs":[{"internalType":"uint256","name":"cost","type":"uint256"},{"internalType":"uint256","name":"costWithFee","type":"uint256"},{"internalType":"uint256","name":"costPerSecond","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getModuleMetadataURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"}],"name":"getPaidAmountsOnActiveAd","outputs":[{"internalType":"uint256","name":"currentPaidAmount","type":"uint256"},{"internalType":"uint256","name":"totalCost","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"moduleOwner","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"uint256","name":"pubId","type":"uint256"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"initializePublicationAction","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"metadataURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minBidIncreaseBps","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"publicationActedProfileId","type":"uint256"},{"internalType":"uint256","name":"publicationActedId","type":"uint256"},{"internalType":"uint256","name":"actorProfileId","type":"uint256"},{"internalType":"address","name":"actorProfileOwner","type":"address"},{"internalType":"address","name":"transactionExecutor","type":"address"},{"internalType":"uint256[]","name":"referrerProfileIds","type":"uint256[]"},{"internalType":"uint256[]","name":"referrerPubIds","type":"uint256[]"},{"internalType":"enum Types.PublicationType[]","name":"referrerPubTypes","type":"uint8[]"},{"internalType":"bytes","name":"actionModuleData","type":"bytes"}],"internalType":"struct Types.ProcessActionParams","name":"processActionParams","type":"tuple"}],"name":"processPublicationAction","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"protocolFeeBps","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_metadataURI","type":"string"}],"name":"setModuleMetadataURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"currency","type":"address"},{"internalType":"uint256","name":"profileId","type":"uint256"}],"name":"withdrawFeesEarned","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"currency","type":"address"}],"name":"withdrawProtocolFees","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60c0346200014257601f620033a438819003918201601f19168301916001600160401b038311848410176200014757808492604094855283398101031262000142576200005a602062000052836200015d565b92016200015d565b81608052620000693362000172565b620000743362000172565b6001600160a01b0391821615801562000137575b62000125571660a052600780546001600160601b0319166b07d003e8000000000000a8c01790556040516131ea9081620001ba82396080518181816105a0015281816106320152818161085e015281816110d00152818161132b015281816114c301528181611b0b01528181611e0401528181612187015281816122bf0152818161248301526130e0015260a0518181816103c401526124320152f35b60405163ddbadd5f60e01b8152600490fd5b508181161562000088565b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b03821682036200014257565b600080546001600160a01b039283166001600160a01b03198216811783559216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a356fe608080604052600436101561001357600080fd5b60003560e01c90816301ffc9a7146126ed5750806303ee438c146103275780630b960220146122715780630bbc0ff714612247578063296bbd271461206a5780632d80caa5146120105780632ee7495714611f7f578063322feb8314611efd57806335659fb814611ed857806343ab3fde14611e8357806347a9fe6d14611e5b5780634ab6c09d14611cff5780635073df5114611cce578063681591c114611b695780636ad025ff1461170b578063715018a6146116a55780638da5cb5b1461167e57806390ce6e081461082257806398bd1061146106e15780639e127f0014610656578063a4c52b8614610612578063ad9dedba146103e8578063b95ddb52146103a4578063c4d66de81461035b578063ce90d52e14610327578063d52b082b146102f6578063dc0d0705146102d1578063e1e7741a146102085763f2fde38b1461015e57600080fd5b3461020357602060031936011261020357610177612a42565b61017f612b30565b6001600160a01b038116156101995761019790612b88565b005b608460405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152fd5b600080fd5b3461020357604060031936011261020357600435610224612ab0565b61022c612b30565b80806102b8575b61028e57816040917f760b3c8b9ff5e893a131c47fe321d02c2f26bcb00be42d784ac7ef9e92dc967893600052600560205261027f81846000209060ff60ff1983541691151516179055565b825191825215156020820152a1005b60046040517f82b42900000000000000000000000000000000000000000000000000000000008152fd5b5081600052600660205260ff6040600020541615610233565b3461020357600060031936011261020357602061ffff60075460501c16604051908152f35b34610203576020600319360112610203576004356000526005602052602060ff604060002054166040519015158152f35b3461020357600060031936011261020357610357610343612898565b604051918291602083526020830190612a1d565b0390f35b3461020357602060031936011261020357610374612a42565b6001600160a01b0380600054161590811591610399575b506102035761019790612b88565b90508116158261038b565b346102035760006003193601126102035760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610203576020806003193601126102035760043590610407826130a4565b6001600160a01b03929083163314158061057e575b61028e57806000526002825260406000209260056040519461043d86612804565b805486528260018201541685870152600281015460408701526003810154606087015260048101546080870152015460ff8116151560a086015261ffff90818160081c1660c087015260181c1660e08501528160005260038352604060002084516000528352604060002060c06104fb6006604051936104bc856127e8565b8054855260018101548886015260028101546040860152600381015495606086019687526004820154608087015260058201541660a086015201612957565b910152518015159081610574575b50610542576002925060005252610197604060002060056000918281558260018201558260028201558260038201558260048201550155565b60248351604051907f11633bb10000000000000000000000000000000000000000000000000000000082526004820152fd5b9050421084610509565b50604051633f1a0f0f60e11b81526004810182905233602482015282816044817f000000000000000000000000000000000000000000000000000000000000000088165afa908115610606576000916105d9575b501561041c565b6105f99150833d85116105ff575b6105f18183612875565b810190612c1d565b846105d2565b503d6105e7565b6040513d6000823e3d90fd5b346102035760006003193601126102035760206040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b3461020357602060031936011261020357600435600052600260205261010060406000208054906001600160a01b03600182015416906002810154906003810154600560048301549201549261ffff94604051968752602087015260408601526060850152608084015260ff8116151560a0840152818160081c1660c084015260181c1660e0820152f35b34610203576103576107fb6106f536612a9a565b9080600052600260205260406000209060405161071181612804565b825481526001600160a01b03918260018501541660208301526005600285015494604084019586526003810154606085015260048101546080850152015460ff8116151560a084015261ffff90818160081c1660c085015260181c1660e08301526000526003602052604060002090516000526020526040600020604051610798816127e8565b81548152600182015460208201526002820154604082015260c06107e26006600385015494606085019586526004810154966080860197885260058201541660a086015201612957565b91015251918215159283610818575b5051905191613023565b604080519384526020840192909252908201529081906060820190565b42109250866107f1565b34610203576003196020813601126102035767ffffffffffffffff60043511610203576101209060043536030112610203576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163303611654576004356004013560005260026020526040600020604051906108a582612804565b80548083526001600160a01b0360018301541660208401526002820154604084015261ffff600560038401549384606087015260048101546080870152015460ff8116151560a0860152818160081c1660c086015260181c1660e084015215908115611638575b5061160e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdd600435360301610104600435013512156102035767ffffffffffffffff60048035610104810135010135116102035760048035610104810135019081013536036024909101136102035760206004803561010481013501908101358101031261020357600435610104810135016024013567ffffffffffffffff81116102035761010060048035610104810135018084019181013501031261020357604051906109db82612804565b60043561010481013501810160248101358352604481013560208401526064810135604084015260848101356060840152610a189060a401612a58565b6080830152610a3460043561010481013501820160c401612a58565b60a083015267ffffffffffffffff60043561010481013501820160e401351161020357610a7f6004803561010481013501908101358101602490810191840160e48101350101612b12565b60c083015261010481816004350135600435010101359067ffffffffffffffff8211610203576004803561010481013501908101358101602401908201830160430112156102035767ffffffffffffffff6004356101048101350182018301602401351161127157602482826101046004350135600435010101013560051b60405192610b0f6020830185612875565b6004803561010481013501808501830160248181013588526020880195938301359092019091019082016044011161020357600435610104810135018401820160440192915b6004356101048101350185018101820160440184106115f95787878760e082015260208101511580156115d9575b6115af5760446004350135600052600560205260ff6040600020541661028e576004356004013560005260036020526040600020825160005260205260406000209160405191610bd2836127e8565b835483526001840154602084015260028401546040840152600384015460608401908152610c216006600487015496608087019788526001600160a01b0360058201541660a088015201612957565b60c0850152519384151594856115a3575b50610c4a906040840151905160208401519187613023565b829492916001600160a01b036020850151169060846004350135906001600160a01b0382168203610203576001600160a01b03604051927f23b872dd000000000000000000000000000000000000000000000000000000006020850152166024830152306044830152806064830152606482528160a081011067ffffffffffffffff60a08401111761127157610ceb82610cf09460a08b9501604052612c35565b612c03565b6001600160a01b036020850151166000526008602052610d166040600020918254612c10565b905560608401519460e0850151956040516020810191604460043501358352604082015260408152610d478161283d565b519020966000975b8751891015610db35760208960051b8901015190818110600014610da25760005260205260406000205b976000198114610d8c5760010197610d4f565b634e487b7160e01b600052601160045260246000fd5b906000526020526040600020610d79565b508861157d575b5061ffff60c0850151169081151580611567575b611398575b505060a0830151151580611382575b806112cd575b61128f578351906001600160a01b0360c086015191610e0b602088015142612c10565b60a087015190919015611287578260a089015116915b60405195610e2e876127e8565b6044600435013587526020870152426040870152606086015260808501521660a083015260c08201526004356004013560005260036020526040600020835160005260205260c06040600020918051835560208101516001840155604081015160028401556060810151600384015560808101516004840155600583016001600160a01b0360a08301511673ffffffffffffffffffffffffffffffffffffffff19825416179055015180519067ffffffffffffffff821161127157610ef660068401546127ae565b601f8111611231575b50602090601f83116001146111c1579180610f33926006946000926111b6575b50506000198260011b9260031b1c19161790565b9101555b6001600160a01b03610f4e600435600401356130a4565b16600052600460205260406000206001600160a01b03602084015116600052602052610f806040600020918254612c10565b90556110c26020604051610f9381612859565b60008152604051610fa381612859565b6000815260405191610fb4836127e8565b600435600401358352604051610fc981612859565b600081528484015260043560040135604084015260246004350135606084015280608084015260a083015260c0820152604051809381927ff90604d1000000000000000000000000000000000000000000000000000000008352846004840152805160248401526110498582015160e06044860152610104850190612a1d565b604082015160648501526060820151608485015260c06110b061109c6080850151937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc94858983030160a48a0152613180565b60a0850151848883030160c4890152613180565b920151908483030160e4850152612a1d565b038160006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165af180156106065761118b575b507fc229f1dfb25655231836c2d767d724926e62c7e57587438ab7bbb70872aa3ecd61035792825161116560c083519301516040519384936004356004013585526020850152604460043501356040850152606084015260a0608084015260a0830190612a1d565b0390a151604051906004356004013560208301526040820152604081526103438161283d565b602090813d83116111af575b6111a18183612875565b8101031261020357826110fd565b503d611197565b015190508880610f1f565b906006840160005260206000209160005b601f1985168110611219575091839160019383601f196006971610611200575b505050811b01910155610f37565b015160001960f88460031b161c191690558780806111f2565b919260206001819286850151815501940192016111d2565b61126190600685016000526020600020601f850160051c81019160208610611267575b601f0160051c0190612bdd565b86610eff565b9091508190611254565b634e487b7160e01b600052604160045260246000fd5b600091610e21565b60246001600160a01b0360a086015116604051907fa54b6f5a0000000000000000000000000000000000000000000000000000000082526004820152fd5b5083516001600160a01b0360a086015116604051917f4bde5ec4000000000000000000000000000000000000000000000000000000008352604460043501356004840152602483015260448201526020816064816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa90811561060657600091611363575b5015610de8565b61137c915060203d6020116105ff576105f18183612875565b8561135c565b506001600160a01b0360a0850151161515610de2565b6113d0929350906113d991610ceb6001600160a01b03608089015116926001600160a01b036020890151169061271096879185612e47565b04938491612de1565b9061ffff60e085015116906001600160a01b03602086015116906000928061141b575b5050509061140d6114139282612c03565b90612c03565b908480610dd3565b6114289192935084612e47565b049061143e60a46004350160043560040161312c565b8091501561155157808304611454575b806113fc565b60005b818110611464575061144e565b61147860a46004350160043560040161312c565b829192101561153b57604051917f6352211e0000000000000000000000000000000000000000000000000000000083528160051b013560048301526020826024816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa918215610606576001926115069160009161150c575b508487049086612de1565b01611457565b61152e915060203d602011611534575b6115268183612875565b810190613085565b8b6114fb565b503d61151c565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601260045260246000fd5b506001600160a01b036080870151161515610dce565b61159c906001600160a01b036020870151169060043560040135612f98565b5085610dba565b42109450610c4a610c32565b60046040517f48be0eb3000000000000000000000000000000000000000000000000000000008152fd5b508051158015906115eb575b15610b83565b5060c08101515115156115e5565b60208060449486358152019401939250610b55565b60046040517fc8df8a36000000000000000000000000000000000000000000000000000000008152fd5b80151591508161164a575b508261090c565b9050421182611643565b60046040517f9de97418000000000000000000000000000000000000000000000000000000008152fd5b346102035760006003193601126102035760206001600160a01b0360005416604051908152f35b34610203576000600319360112610203576116be612b30565b60006001600160a01b03815473ffffffffffffffffffffffffffffffffffffffff1981168355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b346102035760a060031936011261020357600560443510156102035760643567ffffffffffffffff811161020357611747903690600401612a6c565b90608435151560843503610203576117606004356130a4565b6001600160a01b031633141580611ae7575b61028e57600435600052600260205260406000209060056040519261179684612804565b805484526001600160a01b036001820154166020850152600281015460408501526003810154606085015260048101546080850152015460ff8116151560a084015261ffff90818160081c1660c085015260181c1660e08301526004356000526003602052604060002082516000526020526040600020916040519261181b846127e8565b805484526001810154602085015260028101546040850152611868600660038301549260608701938452600481015460808801526001600160a01b0360058201541660a088015201612957565b60c0850152518015159081611add575b501561160e576118986001600160a01b0360208301511684600435612f98565b906000906000906001604435148015611acf575b839015611a8a57506020915085515b80611a33575b5060043560005260038252604060002081516000528252600660406000206000815560006001820155600060028201556000600382015560006004820155600060058201550161191181546127ae565b90816119f6575b50506084356119bb575b51940151604051946004358652602086015260408501526119a557601f19601f7f2106cadd678c167942b51c8796c6273cc5321fa3820b573020cb86f25184f1f9958593604435606086015260e060808601528160e0860152816101009687870137600086838701015260a0850152608435151560c085015201168101030190a1005b634e487b7160e01b600052602160045260246000fd5b600435600052600282526119f1604060002060056000918281558260018201558260028201558260038201558260048201550155565b611922565b81601f60009311600114611a0e5750555b8780611918565b908083918252611a2c601f878420940160051c840160018501612bdd565b5555611a07565b6060817f97c2cf540e8f4d96eccb45d7ff398916dde1bb33eee53d1b5de2364c4973414692600052600685526040600020600160ff198254161790556040519081526001858201526004356040820152a1876118c1565b6119a557602091604435600203611aa457506024356118bb565b611abf604088015167ffffffffffffffff6007541690612c10565b4210156118bb57506004356118bb565b5060009250604435156118ac565b9050421085611878565b50604051633f1a0f0f60e11b815260048035908201523360248201526020816044817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa90811561060657600091611b4b575b5015611772565b611b63915060203d81116105ff576105f18183612875565b83611b44565b34610203576020806003193601126102035767ffffffffffffffff9060043582811161020357611b9d903690600401612b12565b91611ba6612b30565b825190811161127157600191611bbc83546127ae565b601f8111611c81575b5080601f8311600114611c0457508190611bf59394600092611bf95750506000198260011b9260031b1c19161790565b9055005b015190508480610f1f565b90601f19831694846000527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6926000905b878210611c6a57505083859610611c51575b505050811b019055005b015160001960f88460031b161c19169055838080611c47565b808785968294968601518155019501930190611c35565b611cc890846000527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6601f850160051c81019184861061126757601f0160051c0190612bdd565b84611bc5565b34610203576020600319360112610203576004356000526006602052602060ff604060002054166040519015158152f35b3461020357604060031936011261020357611d18612a42565b60243590611d25826130a4565b6001600160a01b039290831633141580611de1575b61028e57611d81611d5861140d611d5084612e5a565b9290946130a4565b938685169687600052600460205260406000209616958660005260205260406000205492612c03565b918215611db7576101979360005260046020526040600020816000526020526040600020611db0848254612c03565b9055612de1565b60046040517f7816c746000000000000000000000000000000000000000000000000000000008152fd5b50604051633f1a0f0f60e11b8152600481018290523360248201526020816044817f000000000000000000000000000000000000000000000000000000000000000088165afa90811561060657600091611e3d575b5015611d3a565b611e55915060203d81116105ff576105f18183612875565b84611e36565b3461020357600060031936011261020357602067ffffffffffffffff60075416604051908152f35b3461020357604060031936011261020357611e9c612a42565b602435906001600160a01b0390818316809303610203571660005260046020526040600020906000526020526020604060002054604051908152f35b3461020357600060031936011261020357602061ffff60075460401c16604051908152f35b34610203576040600319360112610203577f97c2cf540e8f4d96eccb45d7ff398916dde1bb33eee53d1b5de2364c497341466060600435611f3c612ab0565b611f44612b30565b816000526006602052611f688160406000209060ff60ff1983541691151516179055565b6040519182521515602082015260006040820152a1005b3461020357611f8d36612a9a565b906000526003602052604060002090600052602052604060002080546103576001830154926002810154906003810154600482015490611fdd60066001600160a01b036005860154169401612957565b936040519788978852602088015260408701526060860152608085015260a084015260e060c084015260e0830190612a1d565b34610203576020600319360112610203576001600160a01b03612031612a42565b612039612b30565b168060005260086020526040600020548015611db75781610197926000526008602052600060408120553390612de1565b346102035761207836612a9a565b90600052602090600382526040600020906000528152604060002090604051906120a1826127e8565b8254825260018301548183019081526002840154604084015260038401549360608401948552600481015460808501526001600160a01b036120f36006826005850154169360a0880194855201612957565b9560c0860196875251801515908161223d575b501561160e578251958661214957612137965051945b51925191511691604051958695608087526080870190612a1d565b93850152604084015260608301520390f35b50845195604051967fb5a3149600000000000000000000000000000000000000000000000000000000885260048801526024870152600086604481847f0000000000000000000000000000000000000000000000000000000000000000165afa8015610606576000906121c2575b61213796509461211c565b503d806000883e6121d38188612875565b86019584818803126102035780519067ffffffffffffffff821161020357019580601f880112156102035786519661220a88612abf565b916122186040519384612875565b8883528689830101116102035761213797612238918780850191016129fa565b6121b7565b9050421087612106565b34610203576020600319360112610203576040612265600435612e5a565b82519182526020820152f35b34610203576080600319360112610203576044356001600160a01b038116036102035760643567ffffffffffffffff8111610203576122b4903690600401612a6c565b906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001633036116545760e0818381010312610203578035906001600160a01b03821682036102035760208101359283151584036102035761231f60808301612bf4565b9361232c60a08401612bf4565b600435600052600560205260ff6040600020541661028e57600435600052600260205260406000205460036020526040600020816000526020526040600020604051612377816127e8565b81548152600182015460208201526002820154604082015260c06123c6600660038501549460608501958652600481015460808601526001600160a01b0360058201541660a086015201612957565b9101525180151590816126e3575b506126b257506040840135158015612697575b6115af576040517ffe3b3f4c0000000000000000000000000000000000000000000000000000000081526001600160a01b038616600482015260208160248160006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165af1801561060657612678575b50604051633f1a0f0f60e11b815260048035908201523060248201526020816044817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa90811561060657600091612659575b501561262f576103579561259b600561034397604051906124dc82612804565b60243582526001600160a01b0360208301911681526040820160408a01358152606083019060608b01358252608084019260c08c0135845260a085019915158a5260c085019761ffff809116895260e086019916895260043560005260026020526040600020945185556001600160a01b036001860191511673ffffffffffffffffffffffffffffffffffffffff198254161790555160028401555160038301555160048201550193511515849060ff60ff1983541691151516179055565b51907fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff62ffff0064ffff0000008554935160181b169360081b169116171790557fe6d770fc003df8cddca89fef76c93e91ff41c25b93462a2f79f57fc1890a7ebb604051806126256040860135602435600435846040919493926060820195825260208201520152565b0390a13691612adb565b60046040517fa9273f49000000000000000000000000000000000000000000000000000000008152fd5b612672915060203d6020116105ff576105f18183612875565b876124bc565b6126909060203d6020116105ff576105f18183612875565b508661245f565b506060840135151580156123e75750426060850135106123e7565b602490604051907f5fc5043d0000000000000000000000000000000000000000000000000000000082526004820152fd5b90504210886123d4565b3461020357602060031936011261020357600435907fffffffff0000000000000000000000000000000000000000000000000000000091828116809103610203576020927f9b586c28000000000000000000000000000000000000000000000000000000008214928315612769575b5050506040519015158152f35b90919250838101907f4c454e535f4d4f44554c450000000000000000000000000000000000000000008252600b81526127a181612821565b519020161482808061275c565b90600182811c921680156127de575b60208310146127c857565b634e487b7160e01b600052602260045260246000fd5b91607f16916127bd565b60e0810190811067ffffffffffffffff82111761127157604052565b610100810190811067ffffffffffffffff82111761127157604052565b6040810190811067ffffffffffffffff82111761127157604052565b6060810190811067ffffffffffffffff82111761127157604052565b6020810190811067ffffffffffffffff82111761127157604052565b90601f601f19910116810190811067ffffffffffffffff82111761127157604052565b604051906000826001918254926128ae846127ae565b90818452602094818116908160001461293657506001146128da575b50506128d892500383612875565b565b60008181527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf695935091905b81831061291e5750506128d8935082010138806128ca565b85548884018501529485019487945091830191612906565b90506128d895935060ff1991501682840152151560051b82010138806128ca565b9060405191826000825461296a816127ae565b9081845260209460019182811690816000146129d75750600114612998575b5050506128d892500383612875565b600090815285812095935091905b8183106129bf5750506128d89350820101388080612989565b855488840185015294850194879450918301916129a6565b9150506128d895935060ff1991501682840152151560051b820101388080612989565b60005b838110612a0d5750506000910152565b81810151838201526020016129fd565b90601f19601f602093612a3b815180928187528780880191016129fa565b0116010190565b600435906001600160a01b038216820361020357565b35906001600160a01b038216820361020357565b9181601f840112156102035782359167ffffffffffffffff8311610203576020838186019501011161020357565b6003196040910112610203576004359060243590565b60243590811515820361020357565b67ffffffffffffffff811161127157601f01601f191660200190565b929192612ae782612abf565b91612af56040519384612875565b829481845281830111610203578281602093846000960137010152565b9080601f8301121561020357816020612b2d93359101612adb565b90565b6001600160a01b03600054163303612b4457565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b600054906001600160a01b03809116918273ffffffffffffffffffffffffffffffffffffffff19821617600055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b818110612be8575050565b60008155600101612bdd565b359061ffff8216820361020357565b91908203918211610d8c57565b91908201809211610d8c57565b90816020910312610203575180151581036102035790565b604051612cb2916001600160a01b0316612c4e82612821565b6000806020958685527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656487860152868151910182855af13d15612d41573d91612c9683612abf565b92612ca46040519485612875565b83523d60008785013e612d45565b80519081612cbf57505050565b8280612ccf938301019101612c1d565b15612cd75750565b6084906040519062461bcd60e51b82526004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152fd5b6060915b91929015612da65750815115612d59575090565b3b15612d625790565b606460405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152fd5b825190915015612db95750805190602001fd5b612ddd9060405191829162461bcd60e51b8352602060048401526024830190612a1d565b0390fd5b916001600160a01b03604051927fa9059cbb000000000000000000000000000000000000000000000000000000006020850152166024830152604482015260448152608081019181831067ffffffffffffffff841117611271576128d892604052612c35565b81810292918115918404141715610d8c57565b906000918083526002602052604080842091815190612e7882612804565b8354825260056001600160a01b03948560018201541660208501526002810154858501526003810154606085015260048101546080850152015460ff8116151560a084015261ffff90818160081c1660c085015260181c1660e08301528552600360205281852090518552602052808420938151612ef5816127e8565b8554815260018601546020820152600286015492810192835260c0612f40600660038901549860608501998a526004810154976080860198895260058201541660a086015201612957565b91015284518015159081612f8e575b5015612f86575090612f7e82612f74612f6c612b2d955142612c03565b845190612e47565b9551905190612c03565b905190612e47565b935050508190565b9050421038612f4f565b612fed939261301d6128d893612fda60408201610ceb612fb9825142612c03565b612f7e612fcc6080870192835190612e47565b936060870151905190612c03565b9687946001600160a01b039182916130a4565b1660005260046020526040600020931692836000526020526040600020613015858254612c03565b9055516130a4565b90612de1565b92939261305a92901561307e57613052915061271061304b61ffff60075460501c1683612e47565b0490612c10565b925b83612e47565b9161307b61271061307461ffff60075460401c1686612e47565b0484612c10565b91565b5092613054565b9081602091031261020357516001600160a01b03811681036102035790565b604051907f6352211e00000000000000000000000000000000000000000000000000000000825260048201526020816024816001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000165afa90811561060657600091613114575090565b612b2d915060203d8111611534576115268183612875565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610203570180359067ffffffffffffffff821161020357602001918160051b3603831361020357565b90815180825260208080930193019160005b8281106131a0575050505090565b83518552938101939281019260010161319256fea26469706673582212201e75bba7463f57a622b8ac0c6874fe87e0bc0a54b344ad30b24ee118e8077e8a64736f6c63430008150033000000000000000000000000db46d1dc155634fbc732f92e853b10b288ad5a1d0000000000000000000000001ed5983f0c883b96f7c35528a1e22eea67de3ff9
Deployed Bytecode
0x608080604052600436101561001357600080fd5b60003560e01c90816301ffc9a7146126ed5750806303ee438c146103275780630b960220146122715780630bbc0ff714612247578063296bbd271461206a5780632d80caa5146120105780632ee7495714611f7f578063322feb8314611efd57806335659fb814611ed857806343ab3fde14611e8357806347a9fe6d14611e5b5780634ab6c09d14611cff5780635073df5114611cce578063681591c114611b695780636ad025ff1461170b578063715018a6146116a55780638da5cb5b1461167e57806390ce6e081461082257806398bd1061146106e15780639e127f0014610656578063a4c52b8614610612578063ad9dedba146103e8578063b95ddb52146103a4578063c4d66de81461035b578063ce90d52e14610327578063d52b082b146102f6578063dc0d0705146102d1578063e1e7741a146102085763f2fde38b1461015e57600080fd5b3461020357602060031936011261020357610177612a42565b61017f612b30565b6001600160a01b038116156101995761019790612b88565b005b608460405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152fd5b600080fd5b3461020357604060031936011261020357600435610224612ab0565b61022c612b30565b80806102b8575b61028e57816040917f760b3c8b9ff5e893a131c47fe321d02c2f26bcb00be42d784ac7ef9e92dc967893600052600560205261027f81846000209060ff60ff1983541691151516179055565b825191825215156020820152a1005b60046040517f82b42900000000000000000000000000000000000000000000000000000000008152fd5b5081600052600660205260ff6040600020541615610233565b3461020357600060031936011261020357602061ffff60075460501c16604051908152f35b34610203576020600319360112610203576004356000526005602052602060ff604060002054166040519015158152f35b3461020357600060031936011261020357610357610343612898565b604051918291602083526020830190612a1d565b0390f35b3461020357602060031936011261020357610374612a42565b6001600160a01b0380600054161590811591610399575b506102035761019790612b88565b90508116158261038b565b346102035760006003193601126102035760206040516001600160a01b037f0000000000000000000000001ed5983f0c883b96f7c35528a1e22eea67de3ff9168152f35b34610203576020806003193601126102035760043590610407826130a4565b6001600160a01b03929083163314158061057e575b61028e57806000526002825260406000209260056040519461043d86612804565b805486528260018201541685870152600281015460408701526003810154606087015260048101546080870152015460ff8116151560a086015261ffff90818160081c1660c087015260181c1660e08501528160005260038352604060002084516000528352604060002060c06104fb6006604051936104bc856127e8565b8054855260018101548886015260028101546040860152600381015495606086019687526004820154608087015260058201541660a086015201612957565b910152518015159081610574575b50610542576002925060005252610197604060002060056000918281558260018201558260028201558260038201558260048201550155565b60248351604051907f11633bb10000000000000000000000000000000000000000000000000000000082526004820152fd5b9050421084610509565b50604051633f1a0f0f60e11b81526004810182905233602482015282816044817f000000000000000000000000db46d1dc155634fbc732f92e853b10b288ad5a1d88165afa908115610606576000916105d9575b501561041c565b6105f99150833d85116105ff575b6105f18183612875565b810190612c1d565b846105d2565b503d6105e7565b6040513d6000823e3d90fd5b346102035760006003193601126102035760206040516001600160a01b037f000000000000000000000000db46d1dc155634fbc732f92e853b10b288ad5a1d168152f35b3461020357602060031936011261020357600435600052600260205261010060406000208054906001600160a01b03600182015416906002810154906003810154600560048301549201549261ffff94604051968752602087015260408601526060850152608084015260ff8116151560a0840152818160081c1660c084015260181c1660e0820152f35b34610203576103576107fb6106f536612a9a565b9080600052600260205260406000209060405161071181612804565b825481526001600160a01b03918260018501541660208301526005600285015494604084019586526003810154606085015260048101546080850152015460ff8116151560a084015261ffff90818160081c1660c085015260181c1660e08301526000526003602052604060002090516000526020526040600020604051610798816127e8565b81548152600182015460208201526002820154604082015260c06107e26006600385015494606085019586526004810154966080860197885260058201541660a086015201612957565b91015251918215159283610818575b5051905191613023565b604080519384526020840192909252908201529081906060820190565b42109250866107f1565b34610203576003196020813601126102035767ffffffffffffffff60043511610203576101209060043536030112610203576001600160a01b037f000000000000000000000000db46d1dc155634fbc732f92e853b10b288ad5a1d163303611654576004356004013560005260026020526040600020604051906108a582612804565b80548083526001600160a01b0360018301541660208401526002820154604084015261ffff600560038401549384606087015260048101546080870152015460ff8116151560a0860152818160081c1660c086015260181c1660e084015215908115611638575b5061160e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdd600435360301610104600435013512156102035767ffffffffffffffff60048035610104810135010135116102035760048035610104810135019081013536036024909101136102035760206004803561010481013501908101358101031261020357600435610104810135016024013567ffffffffffffffff81116102035761010060048035610104810135018084019181013501031261020357604051906109db82612804565b60043561010481013501810160248101358352604481013560208401526064810135604084015260848101356060840152610a189060a401612a58565b6080830152610a3460043561010481013501820160c401612a58565b60a083015267ffffffffffffffff60043561010481013501820160e401351161020357610a7f6004803561010481013501908101358101602490810191840160e48101350101612b12565b60c083015261010481816004350135600435010101359067ffffffffffffffff8211610203576004803561010481013501908101358101602401908201830160430112156102035767ffffffffffffffff6004356101048101350182018301602401351161127157602482826101046004350135600435010101013560051b60405192610b0f6020830185612875565b6004803561010481013501808501830160248181013588526020880195938301359092019091019082016044011161020357600435610104810135018401820160440192915b6004356101048101350185018101820160440184106115f95787878760e082015260208101511580156115d9575b6115af5760446004350135600052600560205260ff6040600020541661028e576004356004013560005260036020526040600020825160005260205260406000209160405191610bd2836127e8565b835483526001840154602084015260028401546040840152600384015460608401908152610c216006600487015496608087019788526001600160a01b0360058201541660a088015201612957565b60c0850152519384151594856115a3575b50610c4a906040840151905160208401519187613023565b829492916001600160a01b036020850151169060846004350135906001600160a01b0382168203610203576001600160a01b03604051927f23b872dd000000000000000000000000000000000000000000000000000000006020850152166024830152306044830152806064830152606482528160a081011067ffffffffffffffff60a08401111761127157610ceb82610cf09460a08b9501604052612c35565b612c03565b6001600160a01b036020850151166000526008602052610d166040600020918254612c10565b905560608401519460e0850151956040516020810191604460043501358352604082015260408152610d478161283d565b519020966000975b8751891015610db35760208960051b8901015190818110600014610da25760005260205260406000205b976000198114610d8c5760010197610d4f565b634e487b7160e01b600052601160045260246000fd5b906000526020526040600020610d79565b508861157d575b5061ffff60c0850151169081151580611567575b611398575b505060a0830151151580611382575b806112cd575b61128f578351906001600160a01b0360c086015191610e0b602088015142612c10565b60a087015190919015611287578260a089015116915b60405195610e2e876127e8565b6044600435013587526020870152426040870152606086015260808501521660a083015260c08201526004356004013560005260036020526040600020835160005260205260c06040600020918051835560208101516001840155604081015160028401556060810151600384015560808101516004840155600583016001600160a01b0360a08301511673ffffffffffffffffffffffffffffffffffffffff19825416179055015180519067ffffffffffffffff821161127157610ef660068401546127ae565b601f8111611231575b50602090601f83116001146111c1579180610f33926006946000926111b6575b50506000198260011b9260031b1c19161790565b9101555b6001600160a01b03610f4e600435600401356130a4565b16600052600460205260406000206001600160a01b03602084015116600052602052610f806040600020918254612c10565b90556110c26020604051610f9381612859565b60008152604051610fa381612859565b6000815260405191610fb4836127e8565b600435600401358352604051610fc981612859565b600081528484015260043560040135604084015260246004350135606084015280608084015260a083015260c0820152604051809381927ff90604d1000000000000000000000000000000000000000000000000000000008352846004840152805160248401526110498582015160e06044860152610104850190612a1d565b604082015160648501526060820151608485015260c06110b061109c6080850151937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc94858983030160a48a0152613180565b60a0850151848883030160c4890152613180565b920151908483030160e4850152612a1d565b038160006001600160a01b037f000000000000000000000000db46d1dc155634fbc732f92e853b10b288ad5a1d165af180156106065761118b575b507fc229f1dfb25655231836c2d767d724926e62c7e57587438ab7bbb70872aa3ecd61035792825161116560c083519301516040519384936004356004013585526020850152604460043501356040850152606084015260a0608084015260a0830190612a1d565b0390a151604051906004356004013560208301526040820152604081526103438161283d565b602090813d83116111af575b6111a18183612875565b8101031261020357826110fd565b503d611197565b015190508880610f1f565b906006840160005260206000209160005b601f1985168110611219575091839160019383601f196006971610611200575b505050811b01910155610f37565b015160001960f88460031b161c191690558780806111f2565b919260206001819286850151815501940192016111d2565b61126190600685016000526020600020601f850160051c81019160208610611267575b601f0160051c0190612bdd565b86610eff565b9091508190611254565b634e487b7160e01b600052604160045260246000fd5b600091610e21565b60246001600160a01b0360a086015116604051907fa54b6f5a0000000000000000000000000000000000000000000000000000000082526004820152fd5b5083516001600160a01b0360a086015116604051917f4bde5ec4000000000000000000000000000000000000000000000000000000008352604460043501356004840152602483015260448201526020816064816001600160a01b037f000000000000000000000000db46d1dc155634fbc732f92e853b10b288ad5a1d165afa90811561060657600091611363575b5015610de8565b61137c915060203d6020116105ff576105f18183612875565b8561135c565b506001600160a01b0360a0850151161515610de2565b6113d0929350906113d991610ceb6001600160a01b03608089015116926001600160a01b036020890151169061271096879185612e47565b04938491612de1565b9061ffff60e085015116906001600160a01b03602086015116906000928061141b575b5050509061140d6114139282612c03565b90612c03565b908480610dd3565b6114289192935084612e47565b049061143e60a46004350160043560040161312c565b8091501561155157808304611454575b806113fc565b60005b818110611464575061144e565b61147860a46004350160043560040161312c565b829192101561153b57604051917f6352211e0000000000000000000000000000000000000000000000000000000083528160051b013560048301526020826024816001600160a01b037f000000000000000000000000db46d1dc155634fbc732f92e853b10b288ad5a1d165afa918215610606576001926115069160009161150c575b508487049086612de1565b01611457565b61152e915060203d602011611534575b6115268183612875565b810190613085565b8b6114fb565b503d61151c565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601260045260246000fd5b506001600160a01b036080870151161515610dce565b61159c906001600160a01b036020870151169060043560040135612f98565b5085610dba565b42109450610c4a610c32565b60046040517f48be0eb3000000000000000000000000000000000000000000000000000000008152fd5b508051158015906115eb575b15610b83565b5060c08101515115156115e5565b60208060449486358152019401939250610b55565b60046040517fc8df8a36000000000000000000000000000000000000000000000000000000008152fd5b80151591508161164a575b508261090c565b9050421182611643565b60046040517f9de97418000000000000000000000000000000000000000000000000000000008152fd5b346102035760006003193601126102035760206001600160a01b0360005416604051908152f35b34610203576000600319360112610203576116be612b30565b60006001600160a01b03815473ffffffffffffffffffffffffffffffffffffffff1981168355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b346102035760a060031936011261020357600560443510156102035760643567ffffffffffffffff811161020357611747903690600401612a6c565b90608435151560843503610203576117606004356130a4565b6001600160a01b031633141580611ae7575b61028e57600435600052600260205260406000209060056040519261179684612804565b805484526001600160a01b036001820154166020850152600281015460408501526003810154606085015260048101546080850152015460ff8116151560a084015261ffff90818160081c1660c085015260181c1660e08301526004356000526003602052604060002082516000526020526040600020916040519261181b846127e8565b805484526001810154602085015260028101546040850152611868600660038301549260608701938452600481015460808801526001600160a01b0360058201541660a088015201612957565b60c0850152518015159081611add575b501561160e576118986001600160a01b0360208301511684600435612f98565b906000906000906001604435148015611acf575b839015611a8a57506020915085515b80611a33575b5060043560005260038252604060002081516000528252600660406000206000815560006001820155600060028201556000600382015560006004820155600060058201550161191181546127ae565b90816119f6575b50506084356119bb575b51940151604051946004358652602086015260408501526119a557601f19601f7f2106cadd678c167942b51c8796c6273cc5321fa3820b573020cb86f25184f1f9958593604435606086015260e060808601528160e0860152816101009687870137600086838701015260a0850152608435151560c085015201168101030190a1005b634e487b7160e01b600052602160045260246000fd5b600435600052600282526119f1604060002060056000918281558260018201558260028201558260038201558260048201550155565b611922565b81601f60009311600114611a0e5750555b8780611918565b908083918252611a2c601f878420940160051c840160018501612bdd565b5555611a07565b6060817f97c2cf540e8f4d96eccb45d7ff398916dde1bb33eee53d1b5de2364c4973414692600052600685526040600020600160ff198254161790556040519081526001858201526004356040820152a1876118c1565b6119a557602091604435600203611aa457506024356118bb565b611abf604088015167ffffffffffffffff6007541690612c10565b4210156118bb57506004356118bb565b5060009250604435156118ac565b9050421085611878565b50604051633f1a0f0f60e11b815260048035908201523360248201526020816044817f000000000000000000000000db46d1dc155634fbc732f92e853b10b288ad5a1d6001600160a01b03165afa90811561060657600091611b4b575b5015611772565b611b63915060203d81116105ff576105f18183612875565b83611b44565b34610203576020806003193601126102035767ffffffffffffffff9060043582811161020357611b9d903690600401612b12565b91611ba6612b30565b825190811161127157600191611bbc83546127ae565b601f8111611c81575b5080601f8311600114611c0457508190611bf59394600092611bf95750506000198260011b9260031b1c19161790565b9055005b015190508480610f1f565b90601f19831694846000527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6926000905b878210611c6a57505083859610611c51575b505050811b019055005b015160001960f88460031b161c19169055838080611c47565b808785968294968601518155019501930190611c35565b611cc890846000527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6601f850160051c81019184861061126757601f0160051c0190612bdd565b84611bc5565b34610203576020600319360112610203576004356000526006602052602060ff604060002054166040519015158152f35b3461020357604060031936011261020357611d18612a42565b60243590611d25826130a4565b6001600160a01b039290831633141580611de1575b61028e57611d81611d5861140d611d5084612e5a565b9290946130a4565b938685169687600052600460205260406000209616958660005260205260406000205492612c03565b918215611db7576101979360005260046020526040600020816000526020526040600020611db0848254612c03565b9055612de1565b60046040517f7816c746000000000000000000000000000000000000000000000000000000008152fd5b50604051633f1a0f0f60e11b8152600481018290523360248201526020816044817f000000000000000000000000db46d1dc155634fbc732f92e853b10b288ad5a1d88165afa90811561060657600091611e3d575b5015611d3a565b611e55915060203d81116105ff576105f18183612875565b84611e36565b3461020357600060031936011261020357602067ffffffffffffffff60075416604051908152f35b3461020357604060031936011261020357611e9c612a42565b602435906001600160a01b0390818316809303610203571660005260046020526040600020906000526020526020604060002054604051908152f35b3461020357600060031936011261020357602061ffff60075460401c16604051908152f35b34610203576040600319360112610203577f97c2cf540e8f4d96eccb45d7ff398916dde1bb33eee53d1b5de2364c497341466060600435611f3c612ab0565b611f44612b30565b816000526006602052611f688160406000209060ff60ff1983541691151516179055565b6040519182521515602082015260006040820152a1005b3461020357611f8d36612a9a565b906000526003602052604060002090600052602052604060002080546103576001830154926002810154906003810154600482015490611fdd60066001600160a01b036005860154169401612957565b936040519788978852602088015260408701526060860152608085015260a084015260e060c084015260e0830190612a1d565b34610203576020600319360112610203576001600160a01b03612031612a42565b612039612b30565b168060005260086020526040600020548015611db75781610197926000526008602052600060408120553390612de1565b346102035761207836612a9a565b90600052602090600382526040600020906000528152604060002090604051906120a1826127e8565b8254825260018301548183019081526002840154604084015260038401549360608401948552600481015460808501526001600160a01b036120f36006826005850154169360a0880194855201612957565b9560c0860196875251801515908161223d575b501561160e578251958661214957612137965051945b51925191511691604051958695608087526080870190612a1d565b93850152604084015260608301520390f35b50845195604051967fb5a3149600000000000000000000000000000000000000000000000000000000885260048801526024870152600086604481847f000000000000000000000000db46d1dc155634fbc732f92e853b10b288ad5a1d165afa8015610606576000906121c2575b61213796509461211c565b503d806000883e6121d38188612875565b86019584818803126102035780519067ffffffffffffffff821161020357019580601f880112156102035786519661220a88612abf565b916122186040519384612875565b8883528689830101116102035761213797612238918780850191016129fa565b6121b7565b9050421087612106565b34610203576020600319360112610203576040612265600435612e5a565b82519182526020820152f35b34610203576080600319360112610203576044356001600160a01b038116036102035760643567ffffffffffffffff8111610203576122b4903690600401612a6c565b906001600160a01b037f000000000000000000000000db46d1dc155634fbc732f92e853b10b288ad5a1d1633036116545760e0818381010312610203578035906001600160a01b03821682036102035760208101359283151584036102035761231f60808301612bf4565b9361232c60a08401612bf4565b600435600052600560205260ff6040600020541661028e57600435600052600260205260406000205460036020526040600020816000526020526040600020604051612377816127e8565b81548152600182015460208201526002820154604082015260c06123c6600660038501549460608501958652600481015460808601526001600160a01b0360058201541660a086015201612957565b9101525180151590816126e3575b506126b257506040840135158015612697575b6115af576040517ffe3b3f4c0000000000000000000000000000000000000000000000000000000081526001600160a01b038616600482015260208160248160006001600160a01b037f0000000000000000000000001ed5983f0c883b96f7c35528a1e22eea67de3ff9165af1801561060657612678575b50604051633f1a0f0f60e11b815260048035908201523060248201526020816044817f000000000000000000000000db46d1dc155634fbc732f92e853b10b288ad5a1d6001600160a01b03165afa90811561060657600091612659575b501561262f576103579561259b600561034397604051906124dc82612804565b60243582526001600160a01b0360208301911681526040820160408a01358152606083019060608b01358252608084019260c08c0135845260a085019915158a5260c085019761ffff809116895260e086019916895260043560005260026020526040600020945185556001600160a01b036001860191511673ffffffffffffffffffffffffffffffffffffffff198254161790555160028401555160038301555160048201550193511515849060ff60ff1983541691151516179055565b51907fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff62ffff0064ffff0000008554935160181b169360081b169116171790557fe6d770fc003df8cddca89fef76c93e91ff41c25b93462a2f79f57fc1890a7ebb604051806126256040860135602435600435846040919493926060820195825260208201520152565b0390a13691612adb565b60046040517fa9273f49000000000000000000000000000000000000000000000000000000008152fd5b612672915060203d6020116105ff576105f18183612875565b876124bc565b6126909060203d6020116105ff576105f18183612875565b508661245f565b506060840135151580156123e75750426060850135106123e7565b602490604051907f5fc5043d0000000000000000000000000000000000000000000000000000000082526004820152fd5b90504210886123d4565b3461020357602060031936011261020357600435907fffffffff0000000000000000000000000000000000000000000000000000000091828116809103610203576020927f9b586c28000000000000000000000000000000000000000000000000000000008214928315612769575b5050506040519015158152f35b90919250838101907f4c454e535f4d4f44554c450000000000000000000000000000000000000000008252600b81526127a181612821565b519020161482808061275c565b90600182811c921680156127de575b60208310146127c857565b634e487b7160e01b600052602260045260246000fd5b91607f16916127bd565b60e0810190811067ffffffffffffffff82111761127157604052565b610100810190811067ffffffffffffffff82111761127157604052565b6040810190811067ffffffffffffffff82111761127157604052565b6060810190811067ffffffffffffffff82111761127157604052565b6020810190811067ffffffffffffffff82111761127157604052565b90601f601f19910116810190811067ffffffffffffffff82111761127157604052565b604051906000826001918254926128ae846127ae565b90818452602094818116908160001461293657506001146128da575b50506128d892500383612875565b565b60008181527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf695935091905b81831061291e5750506128d8935082010138806128ca565b85548884018501529485019487945091830191612906565b90506128d895935060ff1991501682840152151560051b82010138806128ca565b9060405191826000825461296a816127ae565b9081845260209460019182811690816000146129d75750600114612998575b5050506128d892500383612875565b600090815285812095935091905b8183106129bf5750506128d89350820101388080612989565b855488840185015294850194879450918301916129a6565b9150506128d895935060ff1991501682840152151560051b820101388080612989565b60005b838110612a0d5750506000910152565b81810151838201526020016129fd565b90601f19601f602093612a3b815180928187528780880191016129fa565b0116010190565b600435906001600160a01b038216820361020357565b35906001600160a01b038216820361020357565b9181601f840112156102035782359167ffffffffffffffff8311610203576020838186019501011161020357565b6003196040910112610203576004359060243590565b60243590811515820361020357565b67ffffffffffffffff811161127157601f01601f191660200190565b929192612ae782612abf565b91612af56040519384612875565b829481845281830111610203578281602093846000960137010152565b9080601f8301121561020357816020612b2d93359101612adb565b90565b6001600160a01b03600054163303612b4457565b606460405162461bcd60e51b815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b600054906001600160a01b03809116918273ffffffffffffffffffffffffffffffffffffffff19821617600055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3565b818110612be8575050565b60008155600101612bdd565b359061ffff8216820361020357565b91908203918211610d8c57565b91908201809211610d8c57565b90816020910312610203575180151581036102035790565b604051612cb2916001600160a01b0316612c4e82612821565b6000806020958685527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656487860152868151910182855af13d15612d41573d91612c9683612abf565b92612ca46040519485612875565b83523d60008785013e612d45565b80519081612cbf57505050565b8280612ccf938301019101612c1d565b15612cd75750565b6084906040519062461bcd60e51b82526004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152fd5b6060915b91929015612da65750815115612d59575090565b3b15612d625790565b606460405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152fd5b825190915015612db95750805190602001fd5b612ddd9060405191829162461bcd60e51b8352602060048401526024830190612a1d565b0390fd5b916001600160a01b03604051927fa9059cbb000000000000000000000000000000000000000000000000000000006020850152166024830152604482015260448152608081019181831067ffffffffffffffff841117611271576128d892604052612c35565b81810292918115918404141715610d8c57565b906000918083526002602052604080842091815190612e7882612804565b8354825260056001600160a01b03948560018201541660208501526002810154858501526003810154606085015260048101546080850152015460ff8116151560a084015261ffff90818160081c1660c085015260181c1660e08301528552600360205281852090518552602052808420938151612ef5816127e8565b8554815260018601546020820152600286015492810192835260c0612f40600660038901549860608501998a526004810154976080860198895260058201541660a086015201612957565b91015284518015159081612f8e575b5015612f86575090612f7e82612f74612f6c612b2d955142612c03565b845190612e47565b9551905190612c03565b905190612e47565b935050508190565b9050421038612f4f565b612fed939261301d6128d893612fda60408201610ceb612fb9825142612c03565b612f7e612fcc6080870192835190612e47565b936060870151905190612c03565b9687946001600160a01b039182916130a4565b1660005260046020526040600020931692836000526020526040600020613015858254612c03565b9055516130a4565b90612de1565b92939261305a92901561307e57613052915061271061304b61ffff60075460501c1683612e47565b0490612c10565b925b83612e47565b9161307b61271061307461ffff60075460401c1686612e47565b0484612c10565b91565b5092613054565b9081602091031261020357516001600160a01b03811681036102035790565b604051907f6352211e00000000000000000000000000000000000000000000000000000000825260048201526020816024816001600160a01b037f000000000000000000000000db46d1dc155634fbc732f92e853b10b288ad5a1d165afa90811561060657600091613114575090565b612b2d915060203d8111611534576115268183612875565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610203570180359067ffffffffffffffff821161020357602001918160051b3603831361020357565b90815180825260208080930193019160005b8281106131a0575050505090565b83518552938101939281019260010161319256fea26469706673582212201e75bba7463f57a622b8ac0c6874fe87e0bc0a54b344ad30b24ee118e8077e8a64736f6c63430008150033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000db46d1dc155634fbc732f92e853b10b288ad5a1d0000000000000000000000001ed5983f0c883b96f7c35528a1e22eea67de3ff9
-----Decoded View---------------
Arg [0] : hub (address): 0xDb46d1Dc155634FbC732f92E853b10B288AD5a1d
Arg [1] : _moduleRegistry (address): 0x1eD5983F0c883B96f7C35528a1e22EEA67DE3Ff9
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000db46d1dc155634fbc732f92e853b10b288ad5a1d
Arg [1] : 0000000000000000000000001ed5983f0c883b96f7c35528a1e22eea67de3ff9
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
POL | 100.00% | $0.010303 | 1,320 | $13.6 |
[ 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.