More Info
Private Name Tags
ContractCreator
Loading...
Loading
Contract Name:
TipActionModule
Compiler Version
v0.8.21+commit.d9974bed
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {Types} from "./libraries/Types.sol"; import {IPublicationActionModule} from "./interfaces/IPublicationActionModule.sol"; import {HubRestricted} from "./base/HubRestricted.sol"; import {IModuleRegistry} from "./interfaces/IModuleRegistry.sol"; import {LensModuleMetadata} from "./base/LensModuleMetadata.sol"; import {LensModuleRegistrant} from "./base/LensModuleRegistrant.sol"; /** * @title TipActionModule * @dev Open Action Module for tipping Lens publications. */ contract TipActionModule is IPublicationActionModule, Ownable, HubRestricted, LensModuleMetadata, LensModuleRegistrant { using SafeERC20 for IERC20; error CurrencyNotWhitelisted(); error TipReceiverNotProvided(); error TipAmountCannotBeZero(); event TipReceiverRegistered( uint256 indexed profileId, uint256 indexed pubId, address indexed tipReceiver ); event TipCreated( address indexed transactionExecutor, address indexed tipReceiver, address indexed currency, uint256 tipAmount ); /** * @dev Mapping of tip receivers for publications. */ mapping(uint256 profileId => mapping(uint256 pubId => address tipReceiver)) internal _tipReceivers; /** * @dev Initializes the TipActionModule contract. * @param hub Address of the LensHub contract. * @param moduleRegistry Address of the ModuleRegistry contract. */ constructor( address hub, address moduleRegistry ) Ownable() HubRestricted(hub) LensModuleMetadata() LensModuleRegistrant(moduleRegistry) {} /** * @dev Returns the tip receiver for a publication. * @param profileId ID of the profile. * @param pubId ID of the publication. * @return Address of the tip receiver. */ function getTipReceiver( uint256 profileId, uint256 pubId ) public view returns (address) { return _tipReceivers[profileId][pubId]; } function supportsInterface( bytes4 interfaceID ) public pure virtual override returns (bool) { return interfaceID == type(IPublicationActionModule).interfaceId || super.supportsInterface(interfaceID); } function initializePublicationAction( uint256 profileId, uint256 pubId, address /* transactionExecutor */, bytes calldata data ) external override onlyHub returns (bytes memory) { address tipReceiver = abi.decode(data, (address)); if (tipReceiver == address(0)) { revert TipReceiverNotProvided(); } _tipReceivers[profileId][pubId] = tipReceiver; emit TipReceiverRegistered(profileId, pubId, tipReceiver); return data; } function processPublicationAction( Types.ProcessActionParams calldata params ) external override onlyHub returns (bytes memory) { (address currency, uint256 tipAmount) = abi.decode( params.actionModuleData, (address, uint256) ); if (!MODULE_REGISTRY.isErc20CurrencyRegistered(currency)) { revert CurrencyNotWhitelisted(); } if (tipAmount == 0) { revert TipAmountCannotBeZero(); } address tipReceiver = _tipReceivers[params.publicationActedProfileId][ params.publicationActedId ]; IERC20 token = IERC20(currency); emit TipCreated( params.transactionExecutor, tipReceiver, currency, tipAmount ); token.safeTransferFrom( params.transactionExecutor, tipReceiver, tipAmount ); return abi.encode(tipReceiver, currency, tipAmount); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.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. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling 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 (interfaces/IERC165.sol) pragma solidity ^0.8.0; import "../utils/introspection/IERC165.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.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.9.4) (token/ERC20/extensions/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. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ 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]. * * CAUTION: See Security Considerations above. */ 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.9.3) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/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; /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ 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)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ 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"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ 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"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation 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). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // 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 cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.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 * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [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://consensys.net/diligence/blog/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.8.0/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 (last updated v4.9.4) (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; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// 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.19; import {Errors} from "../libraries/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.8.19; import {ILensModule} from "../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 "./LensModule.sol"; abstract contract LensModuleMetadata is LensModule, Ownable { string public metadataURI; 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.6.0; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {ILensModuleRegistrant} from "../interfaces/IModuleRegistrant.sol"; import {IModuleRegistry} from "../interfaces/IModuleRegistry.sol"; import {Types} from "../libraries/Types.sol"; /** * @title LensModuleRegistrant * @author Paul Burke * * @notice This abstract contract adds a public `MODULE_REGISTRY` immutable field, and provides functions * for registering a module in the registry and checking if a module is registered. */ abstract contract LensModuleRegistrant is ILensModuleRegistrant, Ownable { event ModuleRegistered(); IModuleRegistry public immutable MODULE_REGISTRY; constructor(address moduleRegistry) { MODULE_REGISTRY = IModuleRegistry(moduleRegistry); } /// @inheritdoc ILensModuleRegistrant function isRegistered() public view override returns (bool) { return MODULE_REGISTRY.isModuleRegistered(address(this)); } /// @inheritdoc ILensModuleRegistrant function registerModule() external override onlyOwner returns (bool) { if (isRegistered()) { return true; } bool registered = MODULE_REGISTRY.registerModule( address(this), uint256(Types.ModuleType.PUBLICATION_ACTION_MODULE) ); if (registered) { emit ModuleRegistered(); } return registered; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0; import {IERC165} from "@openzeppelin/contracts/interfaces/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.6.0; /** * @title ILensModuleRegistrant * @author Paul Burke * * @notice An interface for registering modules in the module registry */ interface ILensModuleRegistrant { /** * @dev Registers the open action in the module registry * @return True if the module was registered, false otherwise */ function registerModule() external returns (bool); /** * @dev Checks if the module is registered in the module registry * @return True if the module is registered, false otherwise */ function isRegistered() external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; 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); function emitModuleMetadataRefresh(address moduleAddress) external; // 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.8.19; import {Types} from "../libraries/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.8.19; /** * @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 { // TODO: Reverse order, so Paused becomes 0 and the default. This will get rid of the initializer needs. // It needs to be done carefully, as it might pause the protocol in the Lens V2 upgrade. 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. * @param metadataURI The URI to be used for the profile's metadata. */ 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; } // TODO: Shouldn't this be in the modules Types? struct ProcessCollectParams { uint256 publicationCollectedProfileId; uint256 publicationCollectedId; uint256 collectorProfileId; address collectorProfileOwner; address transactionExecutor; uint256[] referrerProfileIds; uint256[] referrerPubIds; Types.PublicationType[] referrerPubTypes; bytes data; } struct ProcessCommentParams { uint256 profileId; address transactionExecutor; uint256 pointedProfileId; uint256 pointedPubId; uint256[] referrerProfileIds; uint256[] referrerPubIds; Types.PublicationType[] referrerPubTypes; bytes data; } struct ProcessQuoteParams { uint256 profileId; address transactionExecutor; uint256 pointedProfileId; uint256 pointedPubId; uint256[] referrerProfileIds; uint256[] referrerPubIds; Types.PublicationType[] referrerPubTypes; bytes data; } struct ProcessMirrorParams { uint256 profileId; 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; address migrationAdmin; } enum ModuleType { __, // Just to avoid 0 as valid ModuleType PUBLICATION_ACTION_MODULE, REFERENCE_MODULE, FOLLOW_MODULE } }
{ "evmVersion": "paris", "libraries": {}, "metadata": { "bytecodeHash": "ipfs", "useLiteralContent": true }, "optimizer": { "enabled": true, "runs": 200 }, "remappings": [], "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
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":"CurrencyNotWhitelisted","type":"error"},{"inputs":[],"name":"NotHub","type":"error"},{"inputs":[],"name":"TipAmountCannotBeZero","type":"error"},{"inputs":[],"name":"TipReceiverNotProvided","type":"error"},{"anonymous":false,"inputs":[],"name":"ModuleRegistered","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":true,"internalType":"address","name":"transactionExecutor","type":"address"},{"indexed":true,"internalType":"address","name":"tipReceiver","type":"address"},{"indexed":true,"internalType":"address","name":"currency","type":"address"},{"indexed":false,"internalType":"uint256","name":"tipAmount","type":"uint256"}],"name":"TipCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"profileId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"pubId","type":"uint256"},{"indexed":true,"internalType":"address","name":"tipReceiver","type":"address"}],"name":"TipReceiverRegistered","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":[],"name":"getModuleMetadataURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"profileId","type":"uint256"},{"internalType":"uint256","name":"pubId","type":"uint256"}],"name":"getTipReceiver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","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":"isRegistered","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"metadataURI","outputs":[{"internalType":"string","name":"","type":"string"}],"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":"params","type":"tuple"}],"name":"processPublicationAction","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"registerModule","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","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"}]
Contract Creation Code
60c060405234801561001057600080fd5b5060405161129338038061129383398101604081905261002f916100c0565b808261003a33610054565b6001600160a01b039081166080521660a052506100f39050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146100bb57600080fd5b919050565b600080604083850312156100d357600080fd5b6100dc836100a4565b91506100ea602084016100a4565b90509250929050565b60805160a05161115861013b600039600081816101fc01528181610471015281816105a301526108040152600081816101d501528181610341015261052201526111586000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c806390ce6e081161008c578063b95ddb5211610066578063b95ddb52146101f7578063ce90d52e1461021e578063e0f0da8514610226578063f2fde38b1461022e57600080fd5b806390ce6e08146101895780639df316501461019c578063a4c52b86146101d057600080fd5b806322366844116100c8578063223668441461013f578063681591c114610147578063715018a61461015c5780638da5cb5b1461016457600080fd5b806301ffc9a7146100ef57806303ee438c146101175780630b9602201461012c575b600080fd5b6101026100fd366004610ca1565b610241565b60405190151581526020015b60405180910390f35b61011f6102a6565b60405161010e9190610d22565b61011f61013a366004610d4a565b610334565b610102610459565b61015a610155366004610df6565b6104e9565b005b61015a610501565b6000546001600160a01b03165b6040516001600160a01b03909116815260200161010e565b61011f610197366004610ea7565b610515565b6101716101aa366004610ee3565b60009182526002602090815260408084209284529190529020546001600160a01b031690565b6101717f000000000000000000000000000000000000000000000000000000000000000081565b6101717f000000000000000000000000000000000000000000000000000000000000000081565b61011f610736565b6101026107c8565b61015a61023c366004610f05565b6108af565b60006001600160e01b0319821663136b0d8560e31b14806102a05750604080516a4c454e535f4d4f44554c4560a81b6020808301919091528251600b818403018152602b90920190925280519101206001600160e01b03198381169116145b92915050565b600180546102b390610f22565b80601f01602080910402602001604051908101604052809291908181526020018280546102df90610f22565b801561032c5780601f106103015761010080835404028352916020019161032c565b820191906000526020600020905b81548152906001019060200180831161030f57829003601f168201915b505050505081565b6060336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461037f576040516313bd2e8360e31b815260040160405180910390fd5b600061038d83850185610f05565b90506001600160a01b0381166103b6576040516316c4f4a960e11b815260040160405180910390fd5b600087815260026020908152604080832089845290915280822080546001600160a01b0319166001600160a01b0385169081179091559051909188918a917fd8766a4dde1c3b5c500372d6448edb28568eedabe9de08a94992f30a5605168291a483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929a9950505050505050505050565b604051631c5ebe2f60e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631c5ebe2f90602401602060405180830381865afa1580156104c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104e49190610f5c565b905090565b6104f161092d565b60016104fd8282610fcc565b5050565b61050961092d565b6105136000610987565b565b6060336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610560576040516313bd2e8360e31b815260040160405180910390fd5b60008061057161010085018561108c565b81019061057e91906110da565b60405163f21b24d760e01b81526001600160a01b0380841660048301529294509092507f00000000000000000000000000000000000000000000000000000000000000009091169063f21b24d790602401602060405180830381865afa1580156105ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106109190610f5c565b61062d576040516317d818f360e21b815260040160405180910390fd5b8060000361064e57604051631cde341160e21b815260040160405180910390fd5b833560009081526002602090815260408083208288013584529091529020546001600160a01b0390811690839081168261068e60a0890160808a01610f05565b6001600160a01b03167fa97c26bcff37e30b62e8fde0564a6b12c848ec32b59c38db21c5742ff60a2d94866040516106c891815260200190565b60405180910390a46106f56106e360a0880160808901610f05565b6001600160a01b0383169084866109d7565b604080516001600160a01b03808516602083015286169181019190915260608101849052608001604051602081830303815290604052945050505050919050565b60606001805461074590610f22565b80601f016020809104026020016040519081016040528092919081815260200182805461077190610f22565b80156107be5780601f10610793576101008083540402835291602001916107be565b820191906000526020600020905b8154815290600101906020018083116107a157829003601f168201915b5050505050905090565b60006107d261092d565b6107da610459565b156107e55750600190565b6040516320d5a27760e11b8152306004820152600160248201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906341ab44ee906044016020604051808303816000875af1158015610855573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108799190610f5c565b905080156104e4576040517fb24617d9cac8b35b25b3bcaf3eb7e8e8e1cbed6ee116121e4e1c08a97743106290600090a1905090565b6108b761092d565b6001600160a01b0381166109215760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b61092a81610987565b50565b6000546001600160a01b031633146105135760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610918565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052610a31908590610a37565b50505050565b6000610a8c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316610b119092919063ffffffff16565b9050805160001480610aad575080806020019051810190610aad9190610f5c565b610b0c5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610918565b505050565b6060610b208484600085610b28565b949350505050565b606082471015610b895760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610918565b600080866001600160a01b03168587604051610ba59190611106565b60006040518083038185875af1925050503d8060008114610be2576040519150601f19603f3d011682016040523d82523d6000602084013e610be7565b606091505b5091509150610bf887838387610c03565b979650505050505050565b60608315610c72578251600003610c6b576001600160a01b0385163b610c6b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610918565b5081610b20565b610b208383815115610c875781518083602001fd5b8060405162461bcd60e51b81526004016109189190610d22565b600060208284031215610cb357600080fd5b81356001600160e01b031981168114610ccb57600080fd5b9392505050565b60005b83811015610ced578181015183820152602001610cd5565b50506000910152565b60008151808452610d0e816020860160208601610cd2565b601f01601f19169290920160200192915050565b602081526000610ccb6020830184610cf6565b6001600160a01b038116811461092a57600080fd5b600080600080600060808688031215610d6257600080fd5b85359450602086013593506040860135610d7b81610d35565b9250606086013567ffffffffffffffff80821115610d9857600080fd5b818801915088601f830112610dac57600080fd5b813581811115610dbb57600080fd5b896020828501011115610dcd57600080fd5b9699959850939650602001949392505050565b634e487b7160e01b600052604160045260246000fd5b600060208284031215610e0857600080fd5b813567ffffffffffffffff80821115610e2057600080fd5b818401915084601f830112610e3457600080fd5b813581811115610e4657610e46610de0565b604051601f8201601f19908116603f01168101908382118183101715610e6e57610e6e610de0565b81604052828152876020848701011115610e8757600080fd5b826020860160208301376000928101602001929092525095945050505050565b600060208284031215610eb957600080fd5b813567ffffffffffffffff811115610ed057600080fd5b82016101208185031215610ccb57600080fd5b60008060408385031215610ef657600080fd5b50508035926020909101359150565b600060208284031215610f1757600080fd5b8135610ccb81610d35565b600181811c90821680610f3657607f821691505b602082108103610f5657634e487b7160e01b600052602260045260246000fd5b50919050565b600060208284031215610f6e57600080fd5b81518015158114610ccb57600080fd5b601f821115610b0c57600081815260208120601f850160051c81016020861015610fa55750805b601f850160051c820191505b81811015610fc457828155600101610fb1565b505050505050565b815167ffffffffffffffff811115610fe657610fe6610de0565b610ffa81610ff48454610f22565b84610f7e565b602080601f83116001811461102f57600084156110175750858301515b600019600386901b1c1916600185901b178555610fc4565b600085815260208120601f198616915b8281101561105e5788860151825594840194600190910190840161103f565b508582101561107c5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000808335601e198436030181126110a357600080fd5b83018035915067ffffffffffffffff8211156110be57600080fd5b6020019150368190038213156110d357600080fd5b9250929050565b600080604083850312156110ed57600080fd5b82356110f881610d35565b946020939093013593505050565b60008251611118818460208701610cd2565b919091019291505056fea26469706673582212201e81dd849470355aa47524bcb30ba7cedd0f75b72f4a4ccd9ba217200cdb02d664736f6c63430008150033000000000000000000000000db46d1dc155634fbc732f92e853b10b288ad5a1d0000000000000000000000001ed5983f0c883b96f7c35528a1e22eea67de3ff9
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100ea5760003560e01c806390ce6e081161008c578063b95ddb5211610066578063b95ddb52146101f7578063ce90d52e1461021e578063e0f0da8514610226578063f2fde38b1461022e57600080fd5b806390ce6e08146101895780639df316501461019c578063a4c52b86146101d057600080fd5b806322366844116100c8578063223668441461013f578063681591c114610147578063715018a61461015c5780638da5cb5b1461016457600080fd5b806301ffc9a7146100ef57806303ee438c146101175780630b9602201461012c575b600080fd5b6101026100fd366004610ca1565b610241565b60405190151581526020015b60405180910390f35b61011f6102a6565b60405161010e9190610d22565b61011f61013a366004610d4a565b610334565b610102610459565b61015a610155366004610df6565b6104e9565b005b61015a610501565b6000546001600160a01b03165b6040516001600160a01b03909116815260200161010e565b61011f610197366004610ea7565b610515565b6101716101aa366004610ee3565b60009182526002602090815260408084209284529190529020546001600160a01b031690565b6101717f000000000000000000000000db46d1dc155634fbc732f92e853b10b288ad5a1d81565b6101717f0000000000000000000000001ed5983f0c883b96f7c35528a1e22eea67de3ff981565b61011f610736565b6101026107c8565b61015a61023c366004610f05565b6108af565b60006001600160e01b0319821663136b0d8560e31b14806102a05750604080516a4c454e535f4d4f44554c4560a81b6020808301919091528251600b818403018152602b90920190925280519101206001600160e01b03198381169116145b92915050565b600180546102b390610f22565b80601f01602080910402602001604051908101604052809291908181526020018280546102df90610f22565b801561032c5780601f106103015761010080835404028352916020019161032c565b820191906000526020600020905b81548152906001019060200180831161030f57829003601f168201915b505050505081565b6060336001600160a01b037f000000000000000000000000db46d1dc155634fbc732f92e853b10b288ad5a1d161461037f576040516313bd2e8360e31b815260040160405180910390fd5b600061038d83850185610f05565b90506001600160a01b0381166103b6576040516316c4f4a960e11b815260040160405180910390fd5b600087815260026020908152604080832089845290915280822080546001600160a01b0319166001600160a01b0385169081179091559051909188918a917fd8766a4dde1c3b5c500372d6448edb28568eedabe9de08a94992f30a5605168291a483838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929a9950505050505050505050565b604051631c5ebe2f60e01b81523060048201526000907f0000000000000000000000001ed5983f0c883b96f7c35528a1e22eea67de3ff96001600160a01b031690631c5ebe2f90602401602060405180830381865afa1580156104c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104e49190610f5c565b905090565b6104f161092d565b60016104fd8282610fcc565b5050565b61050961092d565b6105136000610987565b565b6060336001600160a01b037f000000000000000000000000db46d1dc155634fbc732f92e853b10b288ad5a1d1614610560576040516313bd2e8360e31b815260040160405180910390fd5b60008061057161010085018561108c565b81019061057e91906110da565b60405163f21b24d760e01b81526001600160a01b0380841660048301529294509092507f0000000000000000000000001ed5983f0c883b96f7c35528a1e22eea67de3ff99091169063f21b24d790602401602060405180830381865afa1580156105ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106109190610f5c565b61062d576040516317d818f360e21b815260040160405180910390fd5b8060000361064e57604051631cde341160e21b815260040160405180910390fd5b833560009081526002602090815260408083208288013584529091529020546001600160a01b0390811690839081168261068e60a0890160808a01610f05565b6001600160a01b03167fa97c26bcff37e30b62e8fde0564a6b12c848ec32b59c38db21c5742ff60a2d94866040516106c891815260200190565b60405180910390a46106f56106e360a0880160808901610f05565b6001600160a01b0383169084866109d7565b604080516001600160a01b03808516602083015286169181019190915260608101849052608001604051602081830303815290604052945050505050919050565b60606001805461074590610f22565b80601f016020809104026020016040519081016040528092919081815260200182805461077190610f22565b80156107be5780601f10610793576101008083540402835291602001916107be565b820191906000526020600020905b8154815290600101906020018083116107a157829003601f168201915b5050505050905090565b60006107d261092d565b6107da610459565b156107e55750600190565b6040516320d5a27760e11b8152306004820152600160248201526000907f0000000000000000000000001ed5983f0c883b96f7c35528a1e22eea67de3ff96001600160a01b0316906341ab44ee906044016020604051808303816000875af1158015610855573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108799190610f5c565b905080156104e4576040517fb24617d9cac8b35b25b3bcaf3eb7e8e8e1cbed6ee116121e4e1c08a97743106290600090a1905090565b6108b761092d565b6001600160a01b0381166109215760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b61092a81610987565b50565b6000546001600160a01b031633146105135760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610918565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052610a31908590610a37565b50505050565b6000610a8c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316610b119092919063ffffffff16565b9050805160001480610aad575080806020019051810190610aad9190610f5c565b610b0c5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610918565b505050565b6060610b208484600085610b28565b949350505050565b606082471015610b895760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610918565b600080866001600160a01b03168587604051610ba59190611106565b60006040518083038185875af1925050503d8060008114610be2576040519150601f19603f3d011682016040523d82523d6000602084013e610be7565b606091505b5091509150610bf887838387610c03565b979650505050505050565b60608315610c72578251600003610c6b576001600160a01b0385163b610c6b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610918565b5081610b20565b610b208383815115610c875781518083602001fd5b8060405162461bcd60e51b81526004016109189190610d22565b600060208284031215610cb357600080fd5b81356001600160e01b031981168114610ccb57600080fd5b9392505050565b60005b83811015610ced578181015183820152602001610cd5565b50506000910152565b60008151808452610d0e816020860160208601610cd2565b601f01601f19169290920160200192915050565b602081526000610ccb6020830184610cf6565b6001600160a01b038116811461092a57600080fd5b600080600080600060808688031215610d6257600080fd5b85359450602086013593506040860135610d7b81610d35565b9250606086013567ffffffffffffffff80821115610d9857600080fd5b818801915088601f830112610dac57600080fd5b813581811115610dbb57600080fd5b896020828501011115610dcd57600080fd5b9699959850939650602001949392505050565b634e487b7160e01b600052604160045260246000fd5b600060208284031215610e0857600080fd5b813567ffffffffffffffff80821115610e2057600080fd5b818401915084601f830112610e3457600080fd5b813581811115610e4657610e46610de0565b604051601f8201601f19908116603f01168101908382118183101715610e6e57610e6e610de0565b81604052828152876020848701011115610e8757600080fd5b826020860160208301376000928101602001929092525095945050505050565b600060208284031215610eb957600080fd5b813567ffffffffffffffff811115610ed057600080fd5b82016101208185031215610ccb57600080fd5b60008060408385031215610ef657600080fd5b50508035926020909101359150565b600060208284031215610f1757600080fd5b8135610ccb81610d35565b600181811c90821680610f3657607f821691505b602082108103610f5657634e487b7160e01b600052602260045260246000fd5b50919050565b600060208284031215610f6e57600080fd5b81518015158114610ccb57600080fd5b601f821115610b0c57600081815260208120601f850160051c81016020861015610fa55750805b601f850160051c820191505b81811015610fc457828155600101610fb1565b505050505050565b815167ffffffffffffffff811115610fe657610fe6610de0565b610ffa81610ff48454610f22565b84610f7e565b602080601f83116001811461102f57600084156110175750858301515b600019600386901b1c1916600185901b178555610fc4565b600085815260208120601f198616915b8281101561105e5788860151825594840194600190910190840161103f565b508582101561107c5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000808335601e198436030181126110a357600080fd5b83018035915067ffffffffffffffff8211156110be57600080fd5b6020019150368190038213156110d357600080fd5b9250929050565b600080604083850312156110ed57600080fd5b82356110f881610d35565b946020939093013593505050565b60008251611118818460208701610cd2565b919091019291505056fea26469706673582212201e81dd849470355aa47524bcb30ba7cedd0f75b72f4a4ccd9ba217200cdb02d664736f6c63430008150033
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 |
---|
[ 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.