BaseBase
0x98...3b52
4's Member

4's Member

4-MBR

Collection
Size
465,098
Collectibles
Owners
465,098
100% Unique Owners
This contract's source code is verified!
Contract Metadata
Compiler
0.8.20+commit.a1b79de6
Language
Solidity
Contract Source Code
File 1 of 9: Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)

pragma solidity ^0.8.20;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev The ETH balance of the account is not enough to perform the operation.
     */
    error AddressInsufficientBalance(address account);

    /**
     * @dev There's no code at `target` (it is not a contract).
     */
    error AddressEmptyCode(address target);

    /**
     * @dev A call to an address target failed. The target may have reverted.
     */
    error FailedInnerCall();

    /**
     * @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.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        if (address(this).balance < amount) {
            revert AddressInsufficientBalance(address(this));
        }

        (bool success, ) = recipient.call{value: amount}("");
        if (!success) {
            revert FailedInnerCall();
        }
    }

    /**
     * @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 or custom error, it is bubbled
     * up by this function (like regular Solidity function calls). However, if
     * the call reverted with no returned reason, this function reverts with a
     * {FailedInnerCall} error.
     *
     * 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.
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0);
    }

    /**
     * @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`.
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        if (address(this).balance < value) {
            revert AddressInsufficientBalance(address(this));
        }
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
     * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an
     * unsuccessful call.
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata
    ) internal view returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            // only check if target is a contract if the call was successful and the return data is empty
            // otherwise we already know that it was a contract
            if (returndata.length == 0 && target.code.length == 0) {
                revert AddressEmptyCode(target);
            }
            return returndata;
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
     * revert reason or with a default {FailedInnerCall} error.
     */
    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            return returndata;
        }
    }

    /**
     * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.
     */
    function _revert(bytes memory returndata) 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 FailedInnerCall();
        }
    }
}
Contract Source Code
File 2 of 9: Constants.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.20;

/**
 * @title Constants
 * @author OpenSocial Protocol
 * @notice This library defines constants for the OpenSocial Protocol.
 */
library Constants {
    string internal constant FOLLOW_NFT_NAME_SUFFIX = '-Follower';
    string internal constant FOLLOW_NFT_SYMBOL_SUFFIX = '-Fl';
    string internal constant JOIN_NFT_NAME_INFIX = '-Member';
    string internal constant JOIN_NFT_SYMBOL_INFIX = '-Mb';
    uint8 internal constant MAX_HANDLE_LENGTH = 15;
    uint8 internal constant MIN_HANDLE_LENGTH = 4;
    uint8 internal constant MAX_COMMUNITY_NAME_LENGTH = 63;
    uint16 internal constant MAX_PROFILE_IMAGE_URI_LENGTH = 6000;
    address internal constant ERC6551_REGISTRY = 0x000000006551c19487814612e58FE06813775758;
    bytes32 internal constant COMMUNITY_TBA_SALT =
        0xd51dafa9227bb21dd4efbc739a5c611e802dd0ec1ef35b3dc8da5ad2dca64ae6;
    bytes32 internal constant APP_ADMIN = keccak256('APP_ADMIN');
    bytes32 internal constant GOVERNANCE = keccak256('GOVERNANCE');
    bytes32 internal constant OPERATION = keccak256('OPERATION');
    bytes32 internal constant STATE_ADMIN = keccak256('STATE_ADMIN');
    uint256 internal constant MAX_TAGS_NUMBER = 10;
}
Contract Source Code
File 3 of 9: IAccessControl.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)

pragma solidity ^0.8.20;

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IAccessControl {
    /**
     * @dev The `account` is missing a role.
     */
    error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);

    /**
     * @dev The caller of a function is not the expected one.
     *
     * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
     */
    error AccessControlBadConfirmation();

    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {AccessControl-_setupRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) external view returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `callerConfirmation`.
     */
    function renounceRole(bytes32 role, address callerConfirmation) external;
}
Contract Source Code
File 4 of 9: IERC4906.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.20;

/// @title EIP-721 Metadata Update Extension
interface IERC4906 {
    /// @dev This event emits when the metadata of a token is changed.
    /// So that the third-party platforms such as NFT market could
    /// timely update the images and related attributes of the NFT.
    event MetadataUpdate(uint256 _tokenId);

    /// @dev This event emits when the metadata of a range of tokens is changed.
    /// So that the third-party platforms such as NFT market could
    /// timely update the images and related attributes of the NFTs.
    event BatchMetadataUpdate(uint256 _fromTokenId, uint256 _toTokenId);
}
Contract Source Code
File 5 of 9: IERC5267.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol)

pragma solidity ^0.8.20;

interface IERC5267 {
    /**
     * @dev MAY be emitted to signal that the domain could have changed.
     */
    event EIP712DomainChanged();

    /**
     * @dev returns the fields and values that describe the domain separator used by this contract for EIP-712
     * signature.
     */
    function eip712Domain()
        external
        view
        returns (
            bytes1 fields,
            string memory name,
            string memory version,
            uint256 chainId,
            address verifyingContract,
            bytes32 salt,
            uint256[] memory extensions
        );
}
Contract Source Code
File 6 of 9: IGovernanceLogic.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.20;

import '../../../libraries/OspDataTypes.sol';
import '../../base/IERC4906.sol';
import '@openzeppelin/contracts/interfaces/IERC5267.sol';
import '../../../libraries/Constants.sol';
import '@openzeppelin/contracts/access/IAccessControl.sol';

/**
 * @title IGovernanceLogic
 * @author OpenSocial Protocol
 *
 * @dev This is the interface for the GovernanceLogic contract.
 */
interface IGovernanceLogic is IERC4906, IERC5267, IAccessControl {
    /**
     * @dev Initializes the Profile SBT, setting the initial governance address as well as the name and symbol.
     *
     * @param name The name to set for the osp NFT.
     * @param symbol The symbol to set for the osp NFT.
     */
    function initialize(
        string calldata name,
        string calldata symbol,
        address followSBTImpl,
        address joinNFTImpl,
        address communityNFT
    ) external;

    /**
     * @dev Sets the protocol state to either a global pause, a publishing pause or an unpaused state. This function
     * can only be called by the governance address or the emergency admin address.
     *
     * Note that this reverts if the emergency admin calls it if:
     *      1. The emergency admin is attempting to unpause.
     *      2. The emergency admin is calling while the protocol is already paused.
     *
     * @param newState The state to set, as a member of the ProtocolState enum.
     */
    function setState(OspDataTypes.ProtocolState newState) external;

    /**
     *@dev Adds or removes a super community creator from the whitelist. This function can only be called by the current
     * governance address.
     *
     * @param communityCreator The community creator address to add or remove from the whitelist.
     * @param whitelist Whether or not the community creator should be whitelisted.
     */
    function whitelistSuperCommunityCreator(address communityCreator, bool whitelist) external;

    /**
     * @dev Adds or removes a app from the whitelist. This function can only be called by the
     * current governance address.
     *
     * @param app Reaction about the activity.
     * @param whitelist Whether or not the reaction should be whitelisted.
     */
    function whitelistApp(address app, bool whitelist) external;

    /**
     * @dev Adds or removes a ERC20 token from the whitelist. This function can only be called by the current
     * governance address.
     *
     * @param token ERC20 token address
     * @param whitelist whether or not the token should be whitelisted
     */
    function whitelistToken(address token, bool whitelist) external;

    /**
     * @dev Adds or removes a reserve community handle.This function can only be called by the current governance address.
     *
     * @param handle The handle to reserve.
     * @param isReserve Reserve or not the handle should be reserved.
     */
    function reserveCommunityHandle(string calldata handle, bool isReserve) external;

    /**
     * @dev Sets the base URI for NFTs. This function can only be called by the current governance
     * address.
     *
     * @param baseURI The base URI to set.
     */
    function setBaseURI(string calldata baseURI) external;

    function setERC6551AccountImpl(address accountImpl) external;

    /// ************************
    /// *****VIEW FUNCTIONS*****
    /// ************************

    /**
     * @dev Returns whether or not a super community creator is whitelisted.
     *
     * @param communityCreator The address of the super community creator to check.
     *
     * @return bool True if the super community creator is whitelisted, false otherwise.
     */
    function isSuperCommunityCreatorWhitelisted(
        address communityCreator
    ) external view returns (bool);

    function isAppWhitelisted(address app) external view returns (bool);

    /**
     * @dev Returns whether or not a token is whitelisted.
     *
     * @param token The address of the token to check.
     *
     * @return bool True if the the token whitelisted, false otherwise.
     */
    function isTokenWhitelisted(address token) external view returns (bool);

    /**
     * @dev Returns whether or not a community handle is reserved.
     *
     * @param handle The handle to check.
     *
     * @return bool True if the the handle is reserved, false otherwise.
     */
    function isReserveCommunityHandle(string calldata handle) external view returns (bool);

    /**
     * @dev Returns the base URI for the NFTs.
     *
     * @return string The base URI for the NFTs.
     */
    function getBaseURI() external view returns (string memory);

    /**
     * @dev Returns the follow NFT implementation address.
     *
     * @return address The follow NFT implementation address.
     */
    function getFollowSBTImpl() external view returns (address);

    /**
     * @dev Returns the join NFT implementation address.
     *
     * @return address The join NFT implementation address.
     */
    function getJoinNFTImpl() external view returns (address);

    /**
     * @dev Returns the community NFT address.
     *
     * @return address The community NFT address.
     */
    function getCommunityNFT() external view returns (address);

    function getERC6551AccountImpl() external view returns (address);

    /**
     * @dev Returns the current protocol state.
     *
     * @return ProtocolState The Protocol state, an enum, where:
     *      0: Unpaused
     *      1: PublishingPaused
     *      2: Paused
     */
    function getState() external view returns (OspDataTypes.ProtocolState);

    function updateMetadata() external;

    /**
     * @dev Update The treasure address.This function can only be called by the current governance.
     */
    function setTreasureAddress(address treasure) external;

    /**
     * @dev Get The treasure address.
     */
    function getTreasureAddress() external view returns (address);
}
Contract Source Code
File 7 of 9: JoinNFTProxy.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.20;

import {IGovernanceLogic} from '../core/logics/interfaces/IGovernanceLogic.sol';
import {Proxy} from '@openzeppelin/contracts/proxy/Proxy.sol';
import {Address} from '@openzeppelin/contracts/utils/Address.sol';

contract JoinNFTProxy is Proxy {
    using Address for address;
    address immutable OSP;

    constructor(bytes memory data) {
        OSP = msg.sender;
        IGovernanceLogic(msg.sender).getJoinNFTImpl().functionDelegateCall(data);
    }

    function _implementation() internal view override returns (address) {
        return IGovernanceLogic(OSP).getJoinNFTImpl();
    }
}
Contract Source Code
File 8 of 9: OspDataTypes.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.20;

/**
 * @title OspDataTypes
 * @author OpenSocial Protocol
 *
 * @dev The OspDataTypes library contains data types used throughout the OpenSocial Protocol.
 */
library OspDataTypes {
    bytes32 internal constant EIP712_DOMAIN_TYPEHASH =
        keccak256(
            'EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'
        );
    bytes32 internal constant CREATE_ACTIVITY_WITH_SIG_TYPEHASH =
        keccak256(
            'CreateActivityWithSig(uint256 profileId,uint256 communityId,string contentURI,bytes extensionInitCode,bytes referenceConditionInitCode,bytes ctx,uint256 nonce,uint256 deadline)'
        );

    bytes32 internal constant CREATE_OPEN_REACTION_WITH_SIG_TYPEHASH =
        keccak256(
            'CreateOpenReactionWithSig(uint256 profileId,uint256 communityId,uint256 referencedProfileId,uint256 referencedContentId,bytes reactionAndData,bytes referenceConditionData,bytes ctx,uint256 nonce,uint256 deadline)'
        );

    bytes32 internal constant CREATE_COMMENT_WITH_SIG_TYPEHASH =
        keccak256(
            'CreateCommentWithSig(uint256 profileId,uint256 communityId,string contentURI,uint256 referencedProfileId,uint256 referencedContentId,bytes referenceConditionInitCode,bytes referenceConditionData,bytes ctx,uint256 nonce,uint256 deadline)'
        );
    /*///////////////////////////////////////////////////////////////
                        Common Type
    //////////////////////////////////////////////////////////////*/

    /**
     * @dev 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 content creation functions are paused.
     * @param Paused The fully paused state.
     */
    enum ProtocolState {
        Unpaused,
        PublishingPaused,
        Paused
    }

    /**
     * @dev A struct containing the necessary information to reconstruct an EIP-712 typed data signature.
     *
     * @param signature Signature
     * @param deadline The signature's deadline
     */
    struct EIP712Signature {
        address signer;
        bytes signature;
        uint256 deadline;
    }

    /*///////////////////////////////////////////////////////////////
                        Storage Struct
    //////////////////////////////////////////////////////////////*/

    /**
     * @dev A struct containing profile data.
     *
     * @param contentCount The number of publications made to this profile.
     * @param followCondition The address of the current follow condition in use by this profile, can be empty.
     * @param followSBT The address of the FollowSBT associated with this profile, can be empty..
     * @param handle The profile's associated handle.
     * @param owner The profile's owner.
     * @param dispatcher The profile's dispatcher.
     * @param mintTimestamp The timestamp at which this profile was minted.
     */
    struct ProfileStruct {
        uint256 contentCount;
        address followCondition;
        address followSBT;
        string handle;
        address owner;
        uint96 mintTimestamp;
        uint256 inviter;
    }

    /**
     * @dev A struct containing community data.
     * @param handle The community's associated handle.
     * @param joinCondition The address of the current join condition in use by this community, can be empty.
     * @param joinNFT The address of the JoinNFT associated with this community.
     */
    struct CommunityStruct {
        string handle;
        address joinCondition;
        address joinNFT;
    }

    struct ContentStruct {
        uint256 communityId;
        uint256 referencedProfileId;
        uint256 referencedContentId;
        string contentURI;
        address extension;
        address referenceCondition;
    }

    struct PluginStruct {
        bool isEnable;
        address tokenAddress;
        uint256 amount;
    }

    /*///////////////////////////////////////////////////////////////
                        Call Params
    //////////////////////////////////////////////////////////////*/

    /**
     * @dev A struct containing the parameters required for the `createProfile()` function.
     *
     * @param handle The handle to set for the profile, must be unique and non-empty.
     * @param followCondition The follow condition to use, can be the zero address.
     * @param followConditionInitData The follow condition initialization data, if any.
     */
    struct CreateProfileData {
        string handle;
        bytes followConditionInitCode;
        uint256 inviter;
        bytes ctx;
    }

    /**
     * Create Activity Data
     * @param profileId The profile id of the creator.
     * @param communityId The community id of the content, if zero then it's a global content.
     * @param contentURI The URI of the content.
     * @param extensionInitCode If set, the extension will be set.
     * @param referenceConditionInitCode If set,the reference condition will be set. contains 20 bytes of condition address, followed by calldata.
     * @param ctx The context data.
     */
    struct CreateActivityData {
        uint256 profileId;
        uint256 communityId;
        string contentURI;
        bytes extensionInitCode;
        bytes referenceConditionInitCode;
        bytes ctx;
    }

    /**
     * Create Comment Data
     * @param profileId The profile id of the commenter.
     * @param communityId
     * @param contentURI
     * @param referencedProfileId
     * @param referencedContentId
     * @param referenceConditionInitCode If set,the reference condition will be set. contains 20 bytes of condition address, followed by calldata.
     * @param referenceConditionData The data passed to the reference condition.
     * @param ctx The context data.
     */
    struct CreateCommentData {
        uint256 profileId;
        uint256 communityId;
        string contentURI;
        uint256 referencedProfileId;
        uint256 referencedContentId;
        bytes referenceConditionInitCode;
        bytes referenceConditionData;
        bytes ctx;
    }

    /**
     * @dev A struct containing the parameters required for the `createMegaphone()` function.
     *
     * @param profileId The profile ID of the user creating the megaphone.
     * @param referencedProfileId The profile ID of the user who created the content being megaphoned.
     * @param referencedContentId The content ID being megaphoned.
     * @param tags The tags to associate with the megaphone.
     * @param startTime The start time of the megaphone.
     * @param duration The duration of the megaphone.
     * @param currency The currency to use for the megaphone.
     * @param amount The amount to pay for the megaphone.
     * @param ctx The context data.
     */
    struct CreateMegaphoneData {
        uint256 profileId;
        uint256 referencedProfileId;
        uint256 referencedContentId;
        string[] tags;
        uint256 startTime;
        uint256 duration;
        address currency;
        uint256 amount;
        bytes ctx;
    }

    /**
     * @dev A struct containing the parameters required for the `createOpenReaction()` function.
     *
     * @param profileId The profile ID of the user creating the reaction.
     * @param communityId The community ID of the content being reacted to.
     * @param referencedProfileId The profile ID of the user who created the content being reacted to.
     * @param referencedContentId The content ID being reacted to.
     * @param reactionAndData The reaction and data to use.
     * @param referenceConditionData The reference condition data to use.
     * @param ctx The context data.
     */
    struct CreateOpenReactionData {
        uint256 profileId;
        uint256 communityId;
        uint256 referencedProfileId;
        uint256 referencedContentId;
        uint256 reactionValue;
        bytes reactionAndData;
        bytes referenceConditionData;
        bytes ctx;
    }

    /**
     * @dev A struct containing the parameters required for the `createCommunity()` function.
     *
     * @param handle The handle to set for the community, must be unique and non-empty.
     * @param communityConditionAndData The community condition and data to use, can be the zero address.
     * @param joinConditionInitCode The join condition initialization data, if any.
     * @param tags The tags to associate with the community.
     * @param ctx The context data.
     */
    struct CreateCommunityData {
        string handle;
        bytes communityConditionAndData;
        bytes joinConditionInitCode;
        string[] tags;
        bytes ctx;
    }

    /**
     * @dev A struct containing the parameters required for the `follow()` function.
     *
     * @param profileId The profile token ID to follow.
     * @param data The data passed to the follow condition.
     * @param ctx The context data.
     */
    struct FollowData {
        uint256 profileId;
        bytes data;
        bytes ctx;
    }

    /**
     * @dev A struct containing the parameters required for the `batchFollow()` function.
     *
     * @param profileIds The array of profile token IDs to follow.
     * @param datas The array of follow condition data parameters to pass to each profile's follow condition.
     * @param ctx The context data.
     */
    struct BatchFollowData {
        uint256[] profileIds;
        bytes[] datas;
        uint256[] values;
        bytes ctx;
    }

    /**
     * @dev A struct containing the parameters required for the `join()` function.
     *
     * @param communityId The ID of the community to join.
     * @param data The data passed to the join condition.
     * @param ctx The context data.
     */
    struct JoinData {
        uint256 communityId;
        bytes data;
        bytes ctx;
    }

    /**
     * @dev A struct containing the parameters required for the `batchJoin()` function.
     * @param communityIds The array of community token IDs to join.
     * @param datas The array of join condition data parameters to pass to each community's join condition.
     * @param values The array of values to pass to each community's join condition.
     * @param ctx The context data.
     */
    struct BatchJoinData {
        uint256[] communityIds;
        bytes[] datas;
        uint256[] values;
        bytes ctx;
    }
}
Contract Source Code
File 9 of 9: Proxy.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/Proxy.sol)

pragma solidity ^0.8.20;

/**
 * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
 * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
 * be specified by overriding the virtual {_implementation} function.
 *
 * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
 * different contract through the {_delegate} function.
 *
 * The success and return data of the delegated call will be returned back to the caller of the proxy.
 */
abstract contract Proxy {
    /**
     * @dev Delegates the current call to `implementation`.
     *
     * This function does not return to its internal call site, it will return directly to the external caller.
     */
    function _delegate(address implementation) internal virtual {
        assembly {
            // Copy msg.data. We take full control of memory in this inline assembly
            // block because it will not return to Solidity code. We overwrite the
            // Solidity scratch pad at memory position 0.
            calldatacopy(0, 0, calldatasize())

            // Call the implementation.
            // out and outsize are 0 because we don't know the size yet.
            let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)

            // Copy the returned data.
            returndatacopy(0, 0, returndatasize())

            switch result
            // delegatecall returns 0 on error.
            case 0 {
                revert(0, returndatasize())
            }
            default {
                return(0, returndatasize())
            }
        }
    }

    /**
     * @dev This is a virtual function that should be overridden so it returns the address to which the fallback
     * function and {_fallback} should delegate.
     */
    function _implementation() internal view virtual returns (address);

    /**
     * @dev Delegates the current call to the address returned by `_implementation()`.
     *
     * This function does not return to its internal call site, it will return directly to the external caller.
     */
    function _fallback() internal virtual {
        _delegate(_implementation());
    }

    /**
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
     * function in the contract matches the call data.
     */
    fallback() external payable virtual {
        _fallback();
    }
}
Settings
{
  "compilationTarget": {
    "contracts/upgradeability/JoinNFTProxy.sol": "JoinNFTProxy"
  },
  "evmVersion": "shanghai",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "remappings": []
}
ABI
[{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"stateMutability":"payable","type":"fallback"}]