// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)pragmasolidity ^0.8.20;import {IAccessControl} from"@openzeppelin/contracts/access/IAccessControl.sol";
import {ContextUpgradeable} from"../utils/ContextUpgradeable.sol";
import {ERC165Upgradeable} from"../utils/introspection/ERC165Upgradeable.sol";
import {Initializable} from"../proxy/utils/Initializable.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```solidity
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```solidity
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
* to enforce additional security measures for this role.
*/abstractcontractAccessControlUpgradeableisInitializable, ContextUpgradeable, IAccessControl, ERC165Upgradeable{
structRoleData {
mapping(address account =>bool) hasRole;
bytes32 adminRole;
}
bytes32publicconstant DEFAULT_ADMIN_ROLE =0x00;
/// @custom:storage-location erc7201:openzeppelin.storage.AccessControlstructAccessControlStorage {
mapping(bytes32 role => RoleData) _roles;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.AccessControl")) - 1)) & ~bytes32(uint256(0xff))bytes32privateconstant AccessControlStorageLocation =0x02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800;
function_getAccessControlStorage() privatepurereturns (AccessControlStorage storage $) {
assembly {
$.slot:= AccessControlStorageLocation
}
}
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with an {AccessControlUnauthorizedAccount} error including the required role.
*/modifieronlyRole(bytes32 role) {
_checkRole(role);
_;
}
function__AccessControl_init() internalonlyInitializing{
}
function__AccessControl_init_unchained() internalonlyInitializing{
}
/**
* @dev See {IERC165-supportsInterface}.
*/functionsupportsInterface(bytes4 interfaceId) publicviewvirtualoverridereturns (bool) {
return interfaceId ==type(IAccessControl).interfaceId||super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/functionhasRole(bytes32 role, address account) publicviewvirtualreturns (bool) {
AccessControlStorage storage $ = _getAccessControlStorage();
return $._roles[role].hasRole[account];
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
* is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
*/function_checkRole(bytes32 role) internalviewvirtual{
_checkRole(role, _msgSender());
}
/**
* @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
* is missing `role`.
*/function_checkRole(bytes32 role, address account) internalviewvirtual{
if (!hasRole(role, account)) {
revert AccessControlUnauthorizedAccount(account, role);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/functiongetRoleAdmin(bytes32 role) publicviewvirtualreturns (bytes32) {
AccessControlStorage storage $ = _getAccessControlStorage();
return $._roles[role].adminRole;
}
/**
* @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.
*
* May emit a {RoleGranted} event.
*/functiongrantRole(bytes32 role, address account) publicvirtualonlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleRevoked} event.
*/functionrevokeRole(bytes32 role, address account) publicvirtualonlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @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 revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `callerConfirmation`.
*
* May emit a {RoleRevoked} event.
*/functionrenounceRole(bytes32 role, address callerConfirmation) publicvirtual{
if (callerConfirmation != _msgSender()) {
revert AccessControlBadConfirmation();
}
_revokeRole(role, callerConfirmation);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/function_setRoleAdmin(bytes32 role, bytes32 adminRole) internalvirtual{
AccessControlStorage storage $ = _getAccessControlStorage();
bytes32 previousAdminRole = getRoleAdmin(role);
$._roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/**
* @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/function_grantRole(bytes32 role, address account) internalvirtualreturns (bool) {
AccessControlStorage storage $ = _getAccessControlStorage();
if (!hasRole(role, account)) {
$._roles[role].hasRole[account] =true;
emit RoleGranted(role, account, _msgSender());
returntrue;
} else {
returnfalse;
}
}
/**
* @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.
*
* Internal function without access restriction.
*
* May emit a {RoleRevoked} event.
*/function_revokeRole(bytes32 role, address account) internalvirtualreturns (bool) {
AccessControlStorage storage $ = _getAccessControlStorage();
if (hasRole(role, account)) {
$._roles[role].hasRole[account] =false;
emit RoleRevoked(role, account, _msgSender());
returntrue;
} else {
returnfalse;
}
}
}
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)pragmasolidity ^0.8.20;/**
* @dev Collection of functions related to the address type
*/libraryAddress{
/**
* @dev The ETH balance of the account is not enough to perform the operation.
*/errorAddressInsufficientBalance(address account);
/**
* @dev There's no code at `target` (it is not a contract).
*/errorAddressEmptyCode(address target);
/**
* @dev A call to an address target failed. The target may have reverted.
*/errorFailedInnerCall();
/**
* @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].
*/functionsendValue(addresspayable 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.
*/functionfunctionCall(address target, bytesmemory data) internalreturns (bytesmemory) {
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`.
*/functionfunctionCallWithValue(address target, bytesmemory data, uint256 value) internalreturns (bytesmemory) {
if (address(this).balance< value) {
revert AddressInsufficientBalance(address(this));
}
(bool success, bytesmemory 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.
*/functionfunctionStaticCall(address target, bytesmemory data) internalviewreturns (bytesmemory) {
(bool success, bytesmemory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*/functionfunctionDelegateCall(address target, bytesmemory data) internalreturns (bytesmemory) {
(bool success, bytesmemory 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.
*/functionverifyCallResultFromTarget(address target,
bool success,
bytesmemory returndata
) internalviewreturns (bytesmemory) {
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 contractif (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.
*/functionverifyCallResult(bool success, bytesmemory returndata) internalpurereturns (bytesmemory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
/**
* @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.
*/function_revert(bytesmemory returndata) privatepure{
// Look for revert reason and bubble it up if presentif (returndata.length>0) {
// The easiest way to bubble the revert reason is using memory via assembly/// @solidity memory-safe-assemblyassembly {
let returndata_size :=mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert FailedInnerCall();
}
}
}
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/Context.sol)pragmasolidity ^0.8.20;/**
* @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.
*/abstractcontractContext{
function_msgSender() internalviewvirtualreturns (address) {
returnmsg.sender;
}
function_msgData() internalviewvirtualreturns (bytescalldata) {
returnmsg.data;
}
}
Contract Source Code
File 18 of 124: ContextUpgradeable.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/Context.sol)pragmasolidity ^0.8.20;import {Initializable} from"../proxy/utils/Initializable.sol";
/**
* @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.
*/abstractcontractContextUpgradeableisInitializable{
function__Context_init() internalonlyInitializing{
}
function__Context_init_unchained() internalonlyInitializing{
}
function_msgSender() internalviewvirtualreturns (address) {
returnmsg.sender;
}
function_msgData() internalviewvirtualreturns (bytescalldata) {
returnmsg.data;
}
}
Contract Source Code
File 19 of 124: ContractMetadata.sol
// SPDX-License-Identifier: Apache-2.0pragmasolidity ^0.8.0;/// @author thirdwebimport"../interface/IContractMetadata.sol";
/**
* @author thirdweb.com
*
* @title Contract Metadata
* @notice Thirdweb's `ContractMetadata` is a contract extension for any base contracts. It lets you set a metadata URI
* for you contract.
* Additionally, `ContractMetadata` is necessary for NFT contracts that want royalties to get distributed on OpenSea.
*/libraryContractMetadataStorage{
/// @custom:storage-location erc7201:contract.metadata.storage/// @dev keccak256(abi.encode(uint256(keccak256("contract.metadata.storage")) - 1)) & ~bytes32(uint256(0xff))bytes32publicconstant CONTRACT_METADATA_STORAGE_POSITION =0x4bc804ba64359c0e35e5ed5d90ee596ecaa49a3a930ddcb1470ea0dd625da900;
structData {
/// @notice Returns the contract metadata URI.string contractURI;
}
functiondata() internalpurereturns (Data storage data_) {
bytes32 position = CONTRACT_METADATA_STORAGE_POSITION;
assembly {
data_.slot:= position
}
}
}
abstractcontractContractMetadataisIContractMetadata{
/**
* @notice Lets a contract admin set the URI for contract-level metadata.
* @dev Caller should be authorized to setup contractURI, e.g. contract admin.
* See {_canSetContractURI}.
* Emits {ContractURIUpdated Event}.
*
* @param _uri keccak256 hash of the role. e.g. keccak256("TRANSFER_ROLE")
*/functionsetContractURI(stringmemory _uri) externaloverride{
if (!_canSetContractURI()) {
revert("Not authorized");
}
_setupContractURI(_uri);
}
/// @dev Lets a contract admin set the URI for contract-level metadata.function_setupContractURI(stringmemory _uri) internal{
stringmemory prevURI = _contractMetadataStorage().contractURI;
_contractMetadataStorage().contractURI = _uri;
emit ContractURIUpdated(prevURI, _uri);
}
/// @notice Returns the contract metadata URI.functioncontractURI() publicviewvirtualoverridereturns (stringmemory) {
return _contractMetadataStorage().contractURI;
}
/// @dev Returns the AccountPermissions storage.function_contractMetadataStorage() internalpurereturns (ContractMetadataStorage.Data storage data) {
data = ContractMetadataStorage.data();
}
/// @dev Returns whether contract metadata can be set in the given execution context.function_canSetContractURI() internalviewvirtualreturns (bool);
}
Contract Source Code
File 20 of 124: ECDSA.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol)pragmasolidity ^0.8.20;/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/libraryECDSA{
enumRecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS
}
/**
* @dev The signature derives the `address(0)`.
*/errorECDSAInvalidSignature();
/**
* @dev The signature has an invalid length.
*/errorECDSAInvalidSignatureLength(uint256 length);
/**
* @dev The signature has an S value that is in the upper half order.
*/errorECDSAInvalidSignatureS(bytes32 s);
/**
* @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not
* return address(0) without also returning an error description. Errors are documented using an enum (error type)
* and a bytes32 providing additional information about the error.
*
* If no error is returned, then the address can be used for verification purposes.
*
* The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*/functiontryRecover(bytes32 hash, bytesmemory signature) internalpurereturns (address, RecoverError, bytes32) {
if (signature.length==65) {
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them// currently is to use assembly./// @solidity memory-safe-assemblyassembly {
r :=mload(add(signature, 0x20))
s :=mload(add(signature, 0x40))
v :=byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else {
return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length));
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.
*/functionrecover(bytes32 hash, bytesmemory signature) internalpurereturns (address) {
(address recovered, RecoverError error, bytes32errorArg) = tryRecover(hash, signature);
_throwError(error, errorArg);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
*
* See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
*/functiontryRecover(bytes32 hash, bytes32 r, bytes32 vs) internalpurereturns (address, RecoverError, bytes32) {
unchecked {
bytes32 s = vs &bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
// We do not check for an overflow here since the shift operation results in 0 or 1.uint8 v =uint8((uint256(vs) >>255) +27);
return tryRecover(hash, v, r, s);
}
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*/functionrecover(bytes32 hash, bytes32 r, bytes32 vs) internalpurereturns (address) {
(address recovered, RecoverError error, bytes32errorArg) = tryRecover(hash, r, vs);
_throwError(error, errorArg);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*/functiontryRecover(bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internalpurereturns (address, RecoverError, bytes32) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most// signatures from current libraries generate a unique signature with an s-value in the lower half order.//// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept// these malleable signatures as well.if (uint256(s) >0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS, s);
}
// If the signature is valid (and not malleable), return the signer addressaddress signer =ecrecover(hash, v, r, s);
if (signer ==address(0)) {
return (address(0), RecoverError.InvalidSignature, bytes32(0));
}
return (signer, RecoverError.NoError, bytes32(0));
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`,
* `r` and `s` signature fields separately.
*/functionrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internalpurereturns (address) {
(address recovered, RecoverError error, bytes32errorArg) = tryRecover(hash, v, r, s);
_throwError(error, errorArg);
return recovered;
}
/**
* @dev Optionally reverts with the corresponding custom error according to the `error` argument provided.
*/function_throwError(RecoverError error, bytes32 errorArg) privatepure{
if (error == RecoverError.NoError) {
return; // no error: do nothing
} elseif (error == RecoverError.InvalidSignature) {
revert ECDSAInvalidSignature();
} elseif (error == RecoverError.InvalidSignatureLength) {
revert ECDSAInvalidSignatureLength(uint256(errorArg));
} elseif (error == RecoverError.InvalidSignatureS) {
revert ECDSAInvalidSignatureS(errorArg);
}
}
}
Contract Source Code
File 21 of 124: EIP712Base.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;import'../../libraries/OspDataTypes.sol';
import'../../libraries/OspErrors.sol';
import'@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol';
/**
* @title EIP712Base
* @author OpenSocial Protocol
* @dev This contract is EIP712 implementation.
* See https://eips.ethereum.org/EIPS/eip-712
*/abstractcontractEIP712Base{
usingSignatureCheckerforaddress;
bytes32internalconstant EIP712_REVISION_HASH =keccak256('1');
/**
* @dev Wrapper for ecrecover to reduce code size, used in meta-tx specific functions.
*/function_validateRecoveredAddress(bytes32 digest,
OspDataTypes.EIP712Signature calldata sig
) internalview{
if (sig.deadline <block.timestamp) revert OspErrors.SignatureExpired();
if (!sig.signer.isValidSignatureNow(digest, sig.signature)) {
revert OspErrors.SignatureInvalid();
}
}
/**
* @dev Calculates EIP712 DOMAIN_SEPARATOR based on the current contract and chain ID.
*/function_calculateDomainSeparator() internalviewvirtualreturns (bytes32);
/**
* @dev Calculates EIP712 digest based on the current DOMAIN_SEPARATOR.
*
* @param hashedMessage The message hash from which the digest should be calculated.
*
* @return bytes32 A 32-byte output representing the EIP712 digest.
*/function_calculateDigest(bytes32 hashedMessage) internalviewreturns (bytes32) {
bytes32 digest;
unchecked {
digest =keccak256(
abi.encodePacked('\x19\x01', _calculateDomainSeparator(), hashedMessage)
);
}
return digest;
}
}
Contract Source Code
File 22 of 124: ERC165.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)pragmasolidity ^0.8.20;import {IERC165} from"./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*/abstractcontractERC165isIERC165{
/**
* @dev See {IERC165-supportsInterface}.
*/functionsupportsInterface(bytes4 interfaceId) publicviewvirtualreturns (bool) {
return interfaceId ==type(IERC165).interfaceId;
}
}
Contract Source Code
File 23 of 124: ERC165Checker.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165Checker.sol)pragmasolidity ^0.8.20;import {IERC165} from"./IERC165.sol";
/**
* @dev Library used to query support of an interface declared via {IERC165}.
*
* Note that these functions return the actual result of the query: they do not
* `revert` if an interface is not supported. It is up to the caller to decide
* what to do in these cases.
*/libraryERC165Checker{
// As per the EIP-165 spec, no interface should ever match 0xffffffffbytes4privateconstant INTERFACE_ID_INVALID =0xffffffff;
/**
* @dev Returns true if `account` supports the {IERC165} interface.
*/functionsupportsERC165(address account) internalviewreturns (bool) {
// Any contract that implements ERC165 must explicitly indicate support of// InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalidreturn
supportsERC165InterfaceUnchecked(account, type(IERC165).interfaceId) &&!supportsERC165InterfaceUnchecked(account, INTERFACE_ID_INVALID);
}
/**
* @dev Returns true if `account` supports the interface defined by
* `interfaceId`. Support for {IERC165} itself is queried automatically.
*
* See {IERC165-supportsInterface}.
*/functionsupportsInterface(address account, bytes4 interfaceId) internalviewreturns (bool) {
// query support of both ERC165 as per the spec and support of _interfaceIdreturn supportsERC165(account) && supportsERC165InterfaceUnchecked(account, interfaceId);
}
/**
* @dev Returns a boolean array where each value corresponds to the
* interfaces passed in and whether they're supported or not. This allows
* you to batch check interfaces for a contract where your expectation
* is that some interfaces may not be supported.
*
* See {IERC165-supportsInterface}.
*/functiongetSupportedInterfaces(address account,
bytes4[] memory interfaceIds
) internalviewreturns (bool[] memory) {
// an array of booleans corresponding to interfaceIds and whether they're supported or notbool[] memory interfaceIdsSupported =newbool[](interfaceIds.length);
// query support of ERC165 itselfif (supportsERC165(account)) {
// query support of each interface in interfaceIdsfor (uint256 i =0; i < interfaceIds.length; i++) {
interfaceIdsSupported[i] = supportsERC165InterfaceUnchecked(account, interfaceIds[i]);
}
}
return interfaceIdsSupported;
}
/**
* @dev Returns true if `account` supports all the interfaces defined in
* `interfaceIds`. Support for {IERC165} itself is queried automatically.
*
* Batch-querying can lead to gas savings by skipping repeated checks for
* {IERC165} support.
*
* See {IERC165-supportsInterface}.
*/functionsupportsAllInterfaces(address account, bytes4[] memory interfaceIds) internalviewreturns (bool) {
// query support of ERC165 itselfif (!supportsERC165(account)) {
returnfalse;
}
// query support of each interface in interfaceIdsfor (uint256 i =0; i < interfaceIds.length; i++) {
if (!supportsERC165InterfaceUnchecked(account, interfaceIds[i])) {
returnfalse;
}
}
// all interfaces supportedreturntrue;
}
/**
* @notice Query if a contract implements an interface, does not check ERC165 support
* @param account The address of the contract to query for support of an interface
* @param interfaceId The interface identifier, as specified in ERC-165
* @return true if the contract at account indicates support of the interface with
* identifier interfaceId, false otherwise
* @dev Assumes that account contains a contract that supports ERC165, otherwise
* the behavior of this method is undefined. This precondition can be checked
* with {supportsERC165}.
*
* Some precompiled contracts will falsely indicate support for a given interface, so caution
* should be exercised when using this function.
*
* Interface identification is specified in ERC-165.
*/functionsupportsERC165InterfaceUnchecked(address account, bytes4 interfaceId) internalviewreturns (bool) {
// prepare callbytesmemory encodedParams =abi.encodeCall(IERC165.supportsInterface, (interfaceId));
// perform static callbool success;
uint256 returnSize;
uint256 returnValue;
assembly {
success :=staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)
returnSize :=returndatasize()
returnValue :=mload(0x00)
}
return success && returnSize >=0x20&& returnValue >0;
}
}
Contract Source Code
File 24 of 124: ERC165Upgradeable.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)pragmasolidity ^0.8.20;import {IERC165} from"@openzeppelin/contracts/utils/introspection/IERC165.sol";
import {Initializable} from"../../proxy/utils/Initializable.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*/abstractcontractERC165UpgradeableisInitializable, IERC165{
function__ERC165_init() internalonlyInitializing{
}
function__ERC165_init_unchained() internalonlyInitializing{
}
/**
* @dev See {IERC165-supportsInterface}.
*/functionsupportsInterface(bytes4 interfaceId) publicviewvirtualreturns (bool) {
return interfaceId ==type(IERC165).interfaceId;
}
}
Contract Source Code
File 25 of 124: ERC1967Proxy.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (proxy/ERC1967/ERC1967Proxy.sol)pragmasolidity ^0.8.20;import {Proxy} from"../Proxy.sol";
import {ERC1967Utils} from"./ERC1967Utils.sol";
/**
* @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an
* implementation address that can be changed. This address is stored in storage in the location specified by
* https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the
* implementation behind the proxy.
*/contractERC1967ProxyisProxy{
/**
* @dev Initializes the upgradeable proxy with an initial implementation specified by `implementation`.
*
* If `_data` is nonempty, it's used as data in a delegate call to `implementation`. This will typically be an
* encoded function call, and allows initializing the storage of the proxy like a Solidity constructor.
*
* Requirements:
*
* - If `data` is empty, `msg.value` must be zero.
*/constructor(address implementation, bytesmemory _data) payable{
ERC1967Utils.upgradeToAndCall(implementation, _data);
}
/**
* @dev Returns the current implementation address.
*
* TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using
* the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
* `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`
*/function_implementation() internalviewvirtualoverridereturns (address) {
return ERC1967Utils.getImplementation();
}
}
Contract Source Code
File 26 of 124: ERC1967Utils.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (proxy/ERC1967/ERC1967Utils.sol)pragmasolidity ^0.8.20;import {IBeacon} from"../beacon/IBeacon.sol";
import {Address} from"../../utils/Address.sol";
import {StorageSlot} from"../../utils/StorageSlot.sol";
/**
* @dev This abstract contract provides getters and event emitting update functions for
* https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
*/libraryERC1967Utils{
// We re-declare ERC-1967 events here because they can't be used directly from IERC1967.// This will be fixed in Solidity 0.8.21. At that point we should remove these events./**
* @dev Emitted when the implementation is upgraded.
*/eventUpgraded(addressindexed implementation);
/**
* @dev Emitted when the admin account has changed.
*/eventAdminChanged(address previousAdmin, address newAdmin);
/**
* @dev Emitted when the beacon is changed.
*/eventBeaconUpgraded(addressindexed beacon);
/**
* @dev Storage slot with the address of the current implementation.
* This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1.
*/// solhint-disable-next-line private-vars-leading-underscorebytes32internalconstant IMPLEMENTATION_SLOT =0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
/**
* @dev The `implementation` of the proxy is invalid.
*/errorERC1967InvalidImplementation(address implementation);
/**
* @dev The `admin` of the proxy is invalid.
*/errorERC1967InvalidAdmin(address admin);
/**
* @dev The `beacon` of the proxy is invalid.
*/errorERC1967InvalidBeacon(address beacon);
/**
* @dev An upgrade function sees `msg.value > 0` that may be lost.
*/errorERC1967NonPayable();
/**
* @dev Returns the current implementation address.
*/functiongetImplementation() internalviewreturns (address) {
return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 implementation slot.
*/function_setImplementation(address newImplementation) private{
if (newImplementation.code.length==0) {
revert ERC1967InvalidImplementation(newImplementation);
}
StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value= newImplementation;
}
/**
* @dev Performs implementation upgrade with additional setup call if data is nonempty.
* This function is payable only if the setup call is performed, otherwise `msg.value` is rejected
* to avoid stuck value in the contract.
*
* Emits an {IERC1967-Upgraded} event.
*/functionupgradeToAndCall(address newImplementation, bytesmemory data) internal{
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
if (data.length>0) {
Address.functionDelegateCall(newImplementation, data);
} else {
_checkNonPayable();
}
}
/**
* @dev Storage slot with the admin of the contract.
* This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1.
*/// solhint-disable-next-line private-vars-leading-underscorebytes32internalconstant ADMIN_SLOT =0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
/**
* @dev Returns the current admin.
*
* TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using
* the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
* `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`
*/functiongetAdmin() internalviewreturns (address) {
return StorageSlot.getAddressSlot(ADMIN_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 admin slot.
*/function_setAdmin(address newAdmin) private{
if (newAdmin ==address(0)) {
revert ERC1967InvalidAdmin(address(0));
}
StorageSlot.getAddressSlot(ADMIN_SLOT).value= newAdmin;
}
/**
* @dev Changes the admin of the proxy.
*
* Emits an {IERC1967-AdminChanged} event.
*/functionchangeAdmin(address newAdmin) internal{
emit AdminChanged(getAdmin(), newAdmin);
_setAdmin(newAdmin);
}
/**
* @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
* This is the keccak-256 hash of "eip1967.proxy.beacon" subtracted by 1.
*/// solhint-disable-next-line private-vars-leading-underscorebytes32internalconstant BEACON_SLOT =0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
/**
* @dev Returns the current beacon.
*/functiongetBeacon() internalviewreturns (address) {
return StorageSlot.getAddressSlot(BEACON_SLOT).value;
}
/**
* @dev Stores a new beacon in the EIP1967 beacon slot.
*/function_setBeacon(address newBeacon) private{
if (newBeacon.code.length==0) {
revert ERC1967InvalidBeacon(newBeacon);
}
StorageSlot.getAddressSlot(BEACON_SLOT).value= newBeacon;
address beaconImplementation = IBeacon(newBeacon).implementation();
if (beaconImplementation.code.length==0) {
revert ERC1967InvalidImplementation(beaconImplementation);
}
}
/**
* @dev Change the beacon and trigger a setup call if data is nonempty.
* This function is payable only if the setup call is performed, otherwise `msg.value` is rejected
* to avoid stuck value in the contract.
*
* Emits an {IERC1967-BeaconUpgraded} event.
*
* CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since
* it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for
* efficiency.
*/functionupgradeBeaconToAndCall(address newBeacon, bytesmemory data) internal{
_setBeacon(newBeacon);
emit BeaconUpgraded(newBeacon);
if (data.length>0) {
Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
} else {
_checkNonPayable();
}
}
/**
* @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract
* if an upgrade doesn't perform an initialization call.
*/function_checkNonPayable() private{
if (msg.value>0) {
revert ERC1967NonPayable();
}
}
}
Contract Source Code
File 27 of 124: ERC20FeeJoinCond.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;import {OspErrors} from'../../../libraries/OspErrors.sol';
import {FeeConditionBase} from'../FeeConditionBase.sol';
import {JoinConditionBase} from'../../base/JoinConditionBase.sol';
import {IERC20} from'@openzeppelin/contracts/token/ERC20/IERC20.sol';
import {SafeERC20} from'@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';
/**
* @param currency The address of the ERC20 token to be used for the fee.
* @param amount The amount of the ERC20 token to be used for the fee.
* @param recipient The address of the recipient of the fee.
*/structCommunityData {
address currency;
uint256 amount;
address recipient;
}
/**
* @title ERC20FeeJoinCond
* @author OpenSocial
* @notice The condition allows users to join a community by paying a fee in ERC20 tokens.
*/contractERC20FeeJoinCondisFeeConditionBase, JoinConditionBase{
usingSafeERC20forIERC20;
mapping(uint256=> CommunityData) internal _dataByCommunity;
constructor(address osp) JoinConditionBase(osp) {}
/**
* @dev Initializes the condition data for a given community.
*/function_initializeCommunityJoinCondition(uint256 communityId,
bytescalldata data
) internaloverride{
(address currency, uint256 amount, address recipient) =abi.decode(
data,
(address, uint256, address)
);
if (!_tokenWhitelisted(currency) || recipient ==address(0) || amount ==0)
revert OspErrors.InitParamsInvalid();
_dataByCommunity[communityId].amount = amount;
_dataByCommunity[communityId].currency = currency;
_dataByCommunity[communityId].recipient = recipient;
}
/**
* @dev process join,transfer ERC20 token to recipient.
*/function_processJoin(address follower,
uint256 communityId,
bytescalldata data
) internaloverridenonPayable{
uint256 amount = _dataByCommunity[communityId].amount;
address currency = _dataByCommunity[communityId].currency;
_validateDataIsExpected(data, currency, amount);
IERC20(currency).safeTransferFrom(
follower,
_dataByCommunity[communityId].recipient,
amount
);
}
/**
* @dev Returns the community data for a given community, or an empty struct if that community was not initialized
* with this condition.
*/functiongetCommunityData(uint256 communityId) externalviewreturns (CommunityData memory) {
return _dataByCommunity[communityId];
}
}
Contract Source Code
File 28 of 124: ERC2981Upgradeable.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (token/common/ERC2981.sol)pragmasolidity ^0.8.20;import {IERC2981} from"@openzeppelin/contracts/interfaces/IERC2981.sol";
import {IERC165} from"@openzeppelin/contracts/utils/introspection/IERC165.sol";
import {ERC165Upgradeable} from"../../utils/introspection/ERC165Upgradeable.sol";
import {Initializable} from"../../proxy/utils/Initializable.sol";
/**
* @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information.
*
* Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for
* specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first.
*
* Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the
* fee is specified in basis points by default.
*
* IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See
* https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to
* voluntarily pay royalties together with sales, but note that this standard is not yet widely supported.
*/abstractcontractERC2981UpgradeableisInitializable, IERC2981, ERC165Upgradeable{
structRoyaltyInfo {
address receiver;
uint96 royaltyFraction;
}
/// @custom:storage-location erc7201:openzeppelin.storage.ERC2981structERC2981Storage {
RoyaltyInfo _defaultRoyaltyInfo;
mapping(uint256 tokenId => RoyaltyInfo) _tokenRoyaltyInfo;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ERC2981")) - 1)) & ~bytes32(uint256(0xff))bytes32privateconstant ERC2981StorageLocation =0xdaedc9ab023613a7caf35e703657e986ccfad7e3eb0af93a2853f8d65dd86b00;
function_getERC2981Storage() privatepurereturns (ERC2981Storage storage $) {
assembly {
$.slot:= ERC2981StorageLocation
}
}
/**
* @dev The default royalty set is invalid (eg. (numerator / denominator) >= 1).
*/errorERC2981InvalidDefaultRoyalty(uint256 numerator, uint256 denominator);
/**
* @dev The default royalty receiver is invalid.
*/errorERC2981InvalidDefaultRoyaltyReceiver(address receiver);
/**
* @dev The royalty set for an specific `tokenId` is invalid (eg. (numerator / denominator) >= 1).
*/errorERC2981InvalidTokenRoyalty(uint256 tokenId, uint256 numerator, uint256 denominator);
/**
* @dev The royalty receiver for `tokenId` is invalid.
*/errorERC2981InvalidTokenRoyaltyReceiver(uint256 tokenId, address receiver);
function__ERC2981_init() internalonlyInitializing{
}
function__ERC2981_init_unchained() internalonlyInitializing{
}
/**
* @dev See {IERC165-supportsInterface}.
*/functionsupportsInterface(bytes4 interfaceId) publicviewvirtualoverride(IERC165, ERC165Upgradeable) returns (bool) {
return interfaceId ==type(IERC2981).interfaceId||super.supportsInterface(interfaceId);
}
/**
* @inheritdoc IERC2981
*/functionroyaltyInfo(uint256 tokenId, uint256 salePrice) publicviewvirtualreturns (address, uint256) {
ERC2981Storage storage $ = _getERC2981Storage();
RoyaltyInfo memory royalty = $._tokenRoyaltyInfo[tokenId];
if (royalty.receiver ==address(0)) {
royalty = $._defaultRoyaltyInfo;
}
uint256 royaltyAmount = (salePrice * royalty.royaltyFraction) / _feeDenominator();
return (royalty.receiver, royaltyAmount);
}
/**
* @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a
* fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an
* override.
*/function_feeDenominator() internalpurevirtualreturns (uint96) {
return10000;
}
/**
* @dev Sets the royalty information that all ids in this contract will default to.
*
* Requirements:
*
* - `receiver` cannot be the zero address.
* - `feeNumerator` cannot be greater than the fee denominator.
*/function_setDefaultRoyalty(address receiver, uint96 feeNumerator) internalvirtual{
ERC2981Storage storage $ = _getERC2981Storage();
uint256 denominator = _feeDenominator();
if (feeNumerator > denominator) {
// Royalty fee will exceed the sale pricerevert ERC2981InvalidDefaultRoyalty(feeNumerator, denominator);
}
if (receiver ==address(0)) {
revert ERC2981InvalidDefaultRoyaltyReceiver(address(0));
}
$._defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator);
}
/**
* @dev Removes default royalty information.
*/function_deleteDefaultRoyalty() internalvirtual{
ERC2981Storage storage $ = _getERC2981Storage();
delete $._defaultRoyaltyInfo;
}
/**
* @dev Sets the royalty information for a specific token id, overriding the global default.
*
* Requirements:
*
* - `receiver` cannot be the zero address.
* - `feeNumerator` cannot be greater than the fee denominator.
*/function_setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) internalvirtual{
ERC2981Storage storage $ = _getERC2981Storage();
uint256 denominator = _feeDenominator();
if (feeNumerator > denominator) {
// Royalty fee will exceed the sale pricerevert ERC2981InvalidTokenRoyalty(tokenId, feeNumerator, denominator);
}
if (receiver ==address(0)) {
revert ERC2981InvalidTokenRoyaltyReceiver(tokenId, address(0));
}
$._tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator);
}
/**
* @dev Resets royalty information for the token id back to the global default.
*/function_resetTokenRoyalty(uint256 tokenId) internalvirtual{
ERC2981Storage storage $ = _getERC2981Storage();
delete $._tokenRoyaltyInfo[tokenId];
}
}
Contract Source Code
File 29 of 124: ERC6551Account.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;/* solhint-disable no-empty-blocks */import {IERC165} from'@openzeppelin/contracts/utils/introspection/IERC165.sol';
import {IERC721Receiver} from'@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol';
import {IERC1155Receiver} from'@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol';
import {OspErrors} from'../../libraries/OspErrors.sol';
import {OspClient} from'../logics/interfaces/OspClient.sol';
import {IERC721} from'@openzeppelin/contracts/token/ERC721/IERC721.sol';
contractERC6551AccountisIERC721Receiver, IERC1155Receiver{
structExecution {
// The target contract for account to execute.address target;
// The value for the execution.uint256 value;
// The call data for the execution.bytes data;
}
addressimmutable OSP;
uint256public tokenId;
constructor(address osp) {
OSP = osp;
}
/**
* @dev initialize communityId, only callable by OSP
*/functioninitialize(uint256 communityId) external{
if (msg.sender!= OSP) revert OspErrors.NotOSP();
tokenId = communityId;
}
/**
* @dev For previous TBA accounts,initialize communityId.
*/functionsetCommunityId(uint256 communityId) external{
if (tokenId ==0&& OspClient(OSP).getCommunityAccount(communityId) ==address(this)) {
tokenId = communityId;
return;
}
revert OspErrors.InitParamsInvalid();
}
/// @notice Executes a transaction from the account/// @param execution The execution to perform/// @return result The result of the executionfunctionexecute(
Execution calldata execution
) publicpayablevirtualreturns (bytesmemory result) {
_onlyOwner(msg.sender);
result = _exec(execution.target, execution.value, execution.data);
}
/// @notice Executes a batch of transactions from the account/// @dev If any of the transactions revert, the entire batch reverts/// @param executions The executions to perform/// @return results The results of the executionsfunctionexecuteBatch(
Execution[] calldata executions
) publicpayablevirtualreturns (bytes[] memory results) {
_onlyOwner(msg.sender);
uint256 executionsLength = executions.length;
results =newbytes[](executionsLength);
for (uint256 i =0; i < executionsLength; ) {
results[i] = _exec(executions[i].target, executions[i].value, executions[i].data);
unchecked {
++i;
}
}
}
functiononERC721Received(address,
address,
uint256,
bytescalldata) externalpureoverridereturns (bytes4) {
return IERC721Receiver.onERC721Received.selector;
}
functiononERC1155Received(address,
address,
uint256,
uint256,
bytescalldata) externalpureoverridereturns (bytes4) {
return IERC1155Receiver.onERC1155Received.selector;
}
functiononERC1155BatchReceived(address,
address,
uint256[] calldata,
uint256[] calldata,
bytescalldata) externalpureoverridereturns (bytes4) {
return IERC1155Receiver.onERC1155BatchReceived.selector;
}
functionsupportsInterface(bytes4 interfaceId) externalviewvirtualoverridereturns (bool) {
return
interfaceId ==type(IERC721Receiver).interfaceId||
interfaceId ==type(IERC1155Receiver).interfaceId||
interfaceId ==type(IERC165).interfaceId;
}
function_exec(address target,
uint256 value,
bytesmemory data
) internalreturns (bytesmemory result) {
bool success;
(success, result) = target.call{value: value}(data);
if (!success) {
// Directly bubble up revert messagesassembly ('memory-safe') {
revert(add(result, 32), mload(result))
}
}
}
function_onlyOwner(address account) internalview{
if (account != IERC721(OspClient(OSP).getCommunityNFT()).ownerOf(tokenId))
revert OspErrors.NotCommunityOwner();
}
// solhint-disable-next-line no-empty-blocksreceive() externalpayable{}
}
Contract Source Code
File 30 of 124: ERC721BurnableUpgradeable.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/ERC721Burnable.sol)pragmasolidity ^0.8.20;import {ERC721Upgradeable} from"../ERC721Upgradeable.sol";
import {ContextUpgradeable} from"../../../utils/ContextUpgradeable.sol";
import {Initializable} from"../../../proxy/utils/Initializable.sol";
/**
* @title ERC721 Burnable Token
* @dev ERC721 Token that can be burned (destroyed).
*/abstractcontractERC721BurnableUpgradeableisInitializable, ContextUpgradeable, ERC721Upgradeable{
function__ERC721Burnable_init() internalonlyInitializing{
}
function__ERC721Burnable_init_unchained() internalonlyInitializing{
}
/**
* @dev Burns `tokenId`. See {ERC721-_burn}.
*
* Requirements:
*
* - The caller must own `tokenId` or be an approved operator.
*/functionburn(uint256 tokenId) publicvirtual{
// Setting an "auth" arguments enables the `_isAuthorized` check which verifies that the token exists// (from != 0). Therefore, it is not needed to verify that the return value is not 0 here.
_update(address(0), tokenId, _msgSender());
}
}
Contract Source Code
File 31 of 124: ERC721EnumerableUpgradeable.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/ERC721Enumerable.sol)pragmasolidity ^0.8.20;import {ERC721Upgradeable} from"../ERC721Upgradeable.sol";
import {IERC721Enumerable} from"@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol";
import {IERC165} from"@openzeppelin/contracts/utils/introspection/IERC165.sol";
import {Initializable} from"../../../proxy/utils/Initializable.sol";
/**
* @dev This implements an optional extension of {ERC721} defined in the EIP that adds enumerability
* of all the token ids in the contract as well as all token ids owned by each account.
*
* CAUTION: `ERC721` extensions that implement custom `balanceOf` logic, such as `ERC721Consecutive`,
* interfere with enumerability and should not be used together with `ERC721Enumerable`.
*/abstractcontractERC721EnumerableUpgradeableisInitializable, ERC721Upgradeable, IERC721Enumerable{
/// @custom:storage-location erc7201:openzeppelin.storage.ERC721EnumerablestructERC721EnumerableStorage {
mapping(address owner =>mapping(uint256 index =>uint256)) _ownedTokens;
mapping(uint256 tokenId =>uint256) _ownedTokensIndex;
uint256[] _allTokens;
mapping(uint256 tokenId =>uint256) _allTokensIndex;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ERC721Enumerable")) - 1)) & ~bytes32(uint256(0xff))bytes32privateconstant ERC721EnumerableStorageLocation =0x645e039705490088daad89bae25049a34f4a9072d398537b1ab2425f24cbed00;
function_getERC721EnumerableStorage() privatepurereturns (ERC721EnumerableStorage storage $) {
assembly {
$.slot:= ERC721EnumerableStorageLocation
}
}
/**
* @dev An `owner`'s token query was out of bounds for `index`.
*
* NOTE: The owner being `address(0)` indicates a global out of bounds index.
*/errorERC721OutOfBoundsIndex(address owner, uint256 index);
/**
* @dev Batch mint is not allowed.
*/errorERC721EnumerableForbiddenBatchMint();
function__ERC721Enumerable_init() internalonlyInitializing{
}
function__ERC721Enumerable_init_unchained() internalonlyInitializing{
}
/**
* @dev See {IERC165-supportsInterface}.
*/functionsupportsInterface(bytes4 interfaceId) publicviewvirtualoverride(IERC165, ERC721Upgradeable) returns (bool) {
return interfaceId ==type(IERC721Enumerable).interfaceId||super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
*/functiontokenOfOwnerByIndex(address owner, uint256 index) publicviewvirtualreturns (uint256) {
ERC721EnumerableStorage storage $ = _getERC721EnumerableStorage();
if (index >= balanceOf(owner)) {
revert ERC721OutOfBoundsIndex(owner, index);
}
return $._ownedTokens[owner][index];
}
/**
* @dev See {IERC721Enumerable-totalSupply}.
*/functiontotalSupply() publicviewvirtualreturns (uint256) {
ERC721EnumerableStorage storage $ = _getERC721EnumerableStorage();
return $._allTokens.length;
}
/**
* @dev See {IERC721Enumerable-tokenByIndex}.
*/functiontokenByIndex(uint256 index) publicviewvirtualreturns (uint256) {
ERC721EnumerableStorage storage $ = _getERC721EnumerableStorage();
if (index >= totalSupply()) {
revert ERC721OutOfBoundsIndex(address(0), index);
}
return $._allTokens[index];
}
/**
* @dev See {ERC721-_update}.
*/function_update(address to, uint256 tokenId, address auth) internalvirtualoverridereturns (address) {
address previousOwner =super._update(to, tokenId, auth);
if (previousOwner ==address(0)) {
_addTokenToAllTokensEnumeration(tokenId);
} elseif (previousOwner != to) {
_removeTokenFromOwnerEnumeration(previousOwner, tokenId);
}
if (to ==address(0)) {
_removeTokenFromAllTokensEnumeration(tokenId);
} elseif (previousOwner != to) {
_addTokenToOwnerEnumeration(to, tokenId);
}
return previousOwner;
}
/**
* @dev Private function to add a token to this extension's ownership-tracking data structures.
* @param to address representing the new owner of the given token ID
* @param tokenId uint256 ID of the token to be added to the tokens list of the given address
*/function_addTokenToOwnerEnumeration(address to, uint256 tokenId) private{
ERC721EnumerableStorage storage $ = _getERC721EnumerableStorage();
uint256 length = balanceOf(to) -1;
$._ownedTokens[to][length] = tokenId;
$._ownedTokensIndex[tokenId] = length;
}
/**
* @dev Private function to add a token to this extension's token tracking data structures.
* @param tokenId uint256 ID of the token to be added to the tokens list
*/function_addTokenToAllTokensEnumeration(uint256 tokenId) private{
ERC721EnumerableStorage storage $ = _getERC721EnumerableStorage();
$._allTokensIndex[tokenId] = $._allTokens.length;
$._allTokens.push(tokenId);
}
/**
* @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
* while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
* gas optimizations e.g. when performing a transfer operation (avoiding double writes).
* This has O(1) time complexity, but alters the order of the _ownedTokens array.
* @param from address representing the previous owner of the given token ID
* @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
*/function_removeTokenFromOwnerEnumeration(addressfrom, uint256 tokenId) private{
ERC721EnumerableStorage storage $ = _getERC721EnumerableStorage();
// To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and// then delete the last slot (swap and pop).uint256 lastTokenIndex = balanceOf(from);
uint256 tokenIndex = $._ownedTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessaryif (tokenIndex != lastTokenIndex) {
uint256 lastTokenId = $._ownedTokens[from][lastTokenIndex];
$._ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
$._ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
}
// This also deletes the contents at the last position of the arraydelete $._ownedTokensIndex[tokenId];
delete $._ownedTokens[from][lastTokenIndex];
}
/**
* @dev Private function to remove a token from this extension's token tracking data structures.
* This has O(1) time complexity, but alters the order of the _allTokens array.
* @param tokenId uint256 ID of the token to be removed from the tokens list
*/function_removeTokenFromAllTokensEnumeration(uint256 tokenId) private{
ERC721EnumerableStorage storage $ = _getERC721EnumerableStorage();
// To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and// then delete the last slot (swap and pop).uint256 lastTokenIndex = $._allTokens.length-1;
uint256 tokenIndex = $._allTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so// rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding// an 'if' statement (like in _removeTokenFromOwnerEnumeration)uint256 lastTokenId = $._allTokens[lastTokenIndex];
$._allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
$._allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index// This also deletes the contents at the last position of the arraydelete $._allTokensIndex[tokenId];
$._allTokens.pop();
}
/**
* See {ERC721-_increaseBalance}. We need that to account tokens that were minted in batch
*/function_increaseBalance(address account, uint128 amount) internalvirtualoverride{
if (amount >0) {
revert ERC721EnumerableForbiddenBatchMint();
}
super._increaseBalance(account, amount);
}
}
Contract Source Code
File 32 of 124: ERC721Upgradeable.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/ERC721.sol)pragmasolidity ^0.8.20;import {IERC721} from"@openzeppelin/contracts/token/ERC721/IERC721.sol";
import {IERC721Receiver} from"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import {IERC721Metadata} from"@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol";
import {ContextUpgradeable} from"../../utils/ContextUpgradeable.sol";
import {Strings} from"@openzeppelin/contracts/utils/Strings.sol";
import {IERC165} from"@openzeppelin/contracts/utils/introspection/IERC165.sol";
import {ERC165Upgradeable} from"../../utils/introspection/ERC165Upgradeable.sol";
import {IERC721Errors} from"@openzeppelin/contracts/interfaces/draft-IERC6093.sol";
import {Initializable} from"../../proxy/utils/Initializable.sol";
/**
* @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
* the Metadata extension, but not including the Enumerable extension, which is available separately as
* {ERC721Enumerable}.
*/abstractcontractERC721UpgradeableisInitializable, ContextUpgradeable, ERC165Upgradeable, IERC721, IERC721Metadata, IERC721Errors{
usingStringsforuint256;
/// @custom:storage-location erc7201:openzeppelin.storage.ERC721structERC721Storage {
// Token namestring _name;
// Token symbolstring _symbol;
mapping(uint256 tokenId =>address) _owners;
mapping(address owner =>uint256) _balances;
mapping(uint256 tokenId =>address) _tokenApprovals;
mapping(address owner =>mapping(address operator =>bool)) _operatorApprovals;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ERC721")) - 1)) & ~bytes32(uint256(0xff))bytes32privateconstant ERC721StorageLocation =0x80bb2b638cc20bc4d0a60d66940f3ab4a00c1d7b313497ca82fb0b4ab0079300;
function_getERC721Storage() privatepurereturns (ERC721Storage storage $) {
assembly {
$.slot:= ERC721StorageLocation
}
}
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/function__ERC721_init(stringmemory name_, stringmemory symbol_) internalonlyInitializing{
__ERC721_init_unchained(name_, symbol_);
}
function__ERC721_init_unchained(stringmemory name_, stringmemory symbol_) internalonlyInitializing{
ERC721Storage storage $ = _getERC721Storage();
$._name = name_;
$._symbol = symbol_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/functionsupportsInterface(bytes4 interfaceId) publicviewvirtualoverride(ERC165Upgradeable, IERC165) returns (bool) {
return
interfaceId ==type(IERC721).interfaceId||
interfaceId ==type(IERC721Metadata).interfaceId||super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721-balanceOf}.
*/functionbalanceOf(address owner) publicviewvirtualreturns (uint256) {
ERC721Storage storage $ = _getERC721Storage();
if (owner ==address(0)) {
revert ERC721InvalidOwner(address(0));
}
return $._balances[owner];
}
/**
* @dev See {IERC721-ownerOf}.
*/functionownerOf(uint256 tokenId) publicviewvirtualreturns (address) {
return _requireOwned(tokenId);
}
/**
* @dev See {IERC721Metadata-name}.
*/functionname() publicviewvirtualreturns (stringmemory) {
ERC721Storage storage $ = _getERC721Storage();
return $._name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/functionsymbol() publicviewvirtualreturns (stringmemory) {
ERC721Storage storage $ = _getERC721Storage();
return $._symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/functiontokenURI(uint256 tokenId) publicviewvirtualreturns (stringmemory) {
_requireOwned(tokenId);
stringmemory baseURI = _baseURI();
returnbytes(baseURI).length>0 ? string.concat(baseURI, tokenId.toString()) : "";
}
/**
* @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
* token will be the concatenation of the `baseURI` and the `tokenId`. Empty
* by default, can be overridden in child contracts.
*/function_baseURI() internalviewvirtualreturns (stringmemory) {
return"";
}
/**
* @dev See {IERC721-approve}.
*/functionapprove(address to, uint256 tokenId) publicvirtual{
_approve(to, tokenId, _msgSender());
}
/**
* @dev See {IERC721-getApproved}.
*/functiongetApproved(uint256 tokenId) publicviewvirtualreturns (address) {
_requireOwned(tokenId);
return _getApproved(tokenId);
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/functionsetApprovalForAll(address operator, bool approved) publicvirtual{
_setApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/functionisApprovedForAll(address owner, address operator) publicviewvirtualreturns (bool) {
ERC721Storage storage $ = _getERC721Storage();
return $._operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/functiontransferFrom(addressfrom, address to, uint256 tokenId) publicvirtual{
if (to ==address(0)) {
revert ERC721InvalidReceiver(address(0));
}
// Setting an "auth" arguments enables the `_isAuthorized` check which verifies that the token exists// (from != 0). Therefore, it is not needed to verify that the return value is not 0 here.address previousOwner = _update(to, tokenId, _msgSender());
if (previousOwner !=from) {
revert ERC721IncorrectOwner(from, tokenId, previousOwner);
}
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/functionsafeTransferFrom(addressfrom, address to, uint256 tokenId) public{
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/functionsafeTransferFrom(addressfrom, address to, uint256 tokenId, bytesmemory data) publicvirtual{
transferFrom(from, to, tokenId);
_checkOnERC721Received(from, to, tokenId, data);
}
/**
* @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
*
* IMPORTANT: Any overrides to this function that add ownership of tokens not tracked by the
* core ERC721 logic MUST be matched with the use of {_increaseBalance} to keep balances
* consistent with ownership. The invariant to preserve is that for any address `a` the value returned by
* `balanceOf(a)` must be equal to the number of tokens such that `_ownerOf(tokenId)` is `a`.
*/function_ownerOf(uint256 tokenId) internalviewvirtualreturns (address) {
ERC721Storage storage $ = _getERC721Storage();
return $._owners[tokenId];
}
/**
* @dev Returns the approved address for `tokenId`. Returns 0 if `tokenId` is not minted.
*/function_getApproved(uint256 tokenId) internalviewvirtualreturns (address) {
ERC721Storage storage $ = _getERC721Storage();
return $._tokenApprovals[tokenId];
}
/**
* @dev Returns whether `spender` is allowed to manage `owner`'s tokens, or `tokenId` in
* particular (ignoring whether it is owned by `owner`).
*
* WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this
* assumption.
*/function_isAuthorized(address owner, address spender, uint256 tokenId) internalviewvirtualreturns (bool) {
return
spender !=address(0) &&
(owner == spender || isApprovedForAll(owner, spender) || _getApproved(tokenId) == spender);
}
/**
* @dev Checks if `spender` can operate on `tokenId`, assuming the provided `owner` is the actual owner.
* Reverts if `spender` does not have approval from the provided `owner` for the given token or for all its assets
* the `spender` for the specific `tokenId`.
*
* WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this
* assumption.
*/function_checkAuthorized(address owner, address spender, uint256 tokenId) internalviewvirtual{
if (!_isAuthorized(owner, spender, tokenId)) {
if (owner ==address(0)) {
revert ERC721NonexistentToken(tokenId);
} else {
revert ERC721InsufficientApproval(spender, tokenId);
}
}
}
/**
* @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override.
*
* NOTE: the value is limited to type(uint128).max. This protect against _balance overflow. It is unrealistic that
* a uint256 would ever overflow from increments when these increments are bounded to uint128 values.
*
* WARNING: Increasing an account's balance using this function tends to be paired with an override of the
* {_ownerOf} function to resolve the ownership of the corresponding tokens so that balances and ownership
* remain consistent with one another.
*/function_increaseBalance(address account, uint128 value) internalvirtual{
ERC721Storage storage $ = _getERC721Storage();
unchecked {
$._balances[account] += value;
}
}
/**
* @dev Transfers `tokenId` from its current owner to `to`, or alternatively mints (or burns) if the current owner
* (or `to`) is the zero address. Returns the owner of the `tokenId` before the update.
*
* The `auth` argument is optional. If the value passed is non 0, then this function will check that
* `auth` is either the owner of the token, or approved to operate on the token (by the owner).
*
* Emits a {Transfer} event.
*
* NOTE: If overriding this function in a way that tracks balances, see also {_increaseBalance}.
*/function_update(address to, uint256 tokenId, address auth) internalvirtualreturns (address) {
ERC721Storage storage $ = _getERC721Storage();
addressfrom= _ownerOf(tokenId);
// Perform (optional) operator checkif (auth !=address(0)) {
_checkAuthorized(from, auth, tokenId);
}
// Execute the updateif (from!=address(0)) {
// Clear approval. No need to re-authorize or emit the Approval event
_approve(address(0), tokenId, address(0), false);
unchecked {
$._balances[from] -=1;
}
}
if (to !=address(0)) {
unchecked {
$._balances[to] +=1;
}
}
$._owners[tokenId] = to;
emit Transfer(from, to, tokenId);
returnfrom;
}
/**
* @dev Mints `tokenId` and transfers it to `to`.
*
* WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
*
* Requirements:
*
* - `tokenId` must not exist.
* - `to` cannot be the zero address.
*
* Emits a {Transfer} event.
*/function_mint(address to, uint256 tokenId) internal{
if (to ==address(0)) {
revert ERC721InvalidReceiver(address(0));
}
address previousOwner = _update(to, tokenId, address(0));
if (previousOwner !=address(0)) {
revert ERC721InvalidSender(address(0));
}
}
/**
* @dev Mints `tokenId`, transfers it to `to` and checks for `to` acceptance.
*
* Requirements:
*
* - `tokenId` must not exist.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/function_safeMint(address to, uint256 tokenId) internal{
_safeMint(to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/function_safeMint(address to, uint256 tokenId, bytesmemory data) internalvirtual{
_mint(to, tokenId);
_checkOnERC721Received(address(0), to, tokenId, data);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
* This is an internal function that does not check if the sender is authorized to operate on the token.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/function_burn(uint256 tokenId) internal{
address previousOwner = _update(address(0), tokenId, address(0));
if (previousOwner ==address(0)) {
revert ERC721NonexistentToken(tokenId);
}
}
/**
* @dev Transfers `tokenId` from `from` to `to`.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
*
* Emits a {Transfer} event.
*/function_transfer(addressfrom, address to, uint256 tokenId) internal{
if (to ==address(0)) {
revert ERC721InvalidReceiver(address(0));
}
address previousOwner = _update(to, tokenId, address(0));
if (previousOwner ==address(0)) {
revert ERC721NonexistentToken(tokenId);
} elseif (previousOwner !=from) {
revert ERC721IncorrectOwner(from, tokenId, previousOwner);
}
}
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking that contract recipients
* are aware of the ERC721 standard to prevent tokens from being forever locked.
*
* `data` is additional data, it has no specified format and it is sent in call to `to`.
*
* This internal function is like {safeTransferFrom} in the sense that it invokes
* {IERC721Receiver-onERC721Received} on the receiver, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `tokenId` token must exist and be owned by `from`.
* - `to` cannot be the zero address.
* - `from` cannot be the zero address.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/function_safeTransfer(addressfrom, address to, uint256 tokenId) internal{
_safeTransfer(from, to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeTransfer-address-address-uint256-}[`_safeTransfer`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/function_safeTransfer(addressfrom, address to, uint256 tokenId, bytesmemory data) internalvirtual{
_transfer(from, to, tokenId);
_checkOnERC721Received(from, to, tokenId, data);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* The `auth` argument is optional. If the value passed is non 0, then this function will check that `auth` is
* either the owner of the token, or approved to operate on all tokens held by this owner.
*
* Emits an {Approval} event.
*
* Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
*/function_approve(address to, uint256 tokenId, address auth) internal{
_approve(to, tokenId, auth, true);
}
/**
* @dev Variant of `_approve` with an optional flag to enable or disable the {Approval} event. The event is not
* emitted in the context of transfers.
*/function_approve(address to, uint256 tokenId, address auth, bool emitEvent) internalvirtual{
ERC721Storage storage $ = _getERC721Storage();
// Avoid reading the owner unless necessaryif (emitEvent || auth !=address(0)) {
address owner = _requireOwned(tokenId);
// We do not use _isAuthorized because single-token approvals should not be able to call approveif (auth !=address(0) && owner != auth &&!isApprovedForAll(owner, auth)) {
revert ERC721InvalidApprover(auth);
}
if (emitEvent) {
emit Approval(owner, to, tokenId);
}
}
$._tokenApprovals[tokenId] = to;
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Requirements:
* - operator can't be the address zero.
*
* Emits an {ApprovalForAll} event.
*/function_setApprovalForAll(address owner, address operator, bool approved) internalvirtual{
ERC721Storage storage $ = _getERC721Storage();
if (operator ==address(0)) {
revert ERC721InvalidOperator(operator);
}
$._operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @dev Reverts if the `tokenId` doesn't have a current owner (it hasn't been minted, or it has been burned).
* Returns the owner.
*
* Overrides to ownership logic should be done to {_ownerOf}.
*/function_requireOwned(uint256 tokenId) internalviewreturns (address) {
address owner = _ownerOf(tokenId);
if (owner ==address(0)) {
revert ERC721NonexistentToken(tokenId);
}
return owner;
}
/**
* @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target address. This will revert if the
* recipient doesn't accept the token transfer. The call is not executed if the target address is not a contract.
*
* @param from address representing the previous owner of the given token ID
* @param to target address that will receive the tokens
* @param tokenId uint256 ID of the token to be transferred
* @param data bytes optional data to send along with the call
*/function_checkOnERC721Received(addressfrom, address to, uint256 tokenId, bytesmemory data) private{
if (to.code.length>0) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {
if (retval != IERC721Receiver.onERC721Received.selector) {
revert ERC721InvalidReceiver(to);
}
} catch (bytesmemory reason) {
if (reason.length==0) {
revert ERC721InvalidReceiver(to);
} else {
/// @solidity memory-safe-assemblyassembly {
revert(add(32, reason), mload(reason))
}
}
}
}
}
}
Contract Source Code
File 33 of 124: EnumerableSet.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.pragmasolidity ^0.8.20;/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```solidity
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
* unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
* array of EnumerableSet.
* ====
*/libraryEnumerableSet{
// To implement this library for multiple types with as little code// repetition as possible, we write it in terms of a generic Set type with// bytes32 values.// The Set implementation uses private functions, and user-facing// implementations (such as AddressSet) are just wrappers around the// underlying Set.// This means that we can only create new EnumerableSets for types that fit// in bytes32.structSet {
// Storage of set valuesbytes32[] _values;
// Position is the index of the value in the `values` array plus 1.// Position 0 is used to mean a value is not in the set.mapping(bytes32 value =>uint256) _positions;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/function_add(Set storage set, bytes32 value) privatereturns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes// and use 0 as a sentinel value
set._positions[value] = set._values.length;
returntrue;
} else {
returnfalse;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/function_remove(Set storage set, bytes32 value) privatereturns (bool) {
// We cache the value's position to prevent multiple reads from the same storage slotuint256 position = set._positions[value];
if (position !=0) {
// Equivalent to contains(set, value)// To delete an element from the _values array in O(1), we swap the element to delete with the last one in// the array, and then remove the last element (sometimes called as 'swap and pop').// This modifies the order of the array, as noted in {at}.uint256 valueIndex = position -1;
uint256 lastIndex = set._values.length-1;
if (valueIndex != lastIndex) {
bytes32 lastValue = set._values[lastIndex];
// Move the lastValue to the index where the value to delete is
set._values[valueIndex] = lastValue;
// Update the tracked position of the lastValue (that was just moved)
set._positions[lastValue] = position;
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the tracked position for the deleted slotdelete set._positions[value];
returntrue;
} else {
returnfalse;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/function_contains(Set storage set, bytes32 value) privateviewreturns (bool) {
return set._positions[value] !=0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/function_length(Set storage set) privateviewreturns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/function_at(Set storage set, uint256 index) privateviewreturns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/function_values(Set storage set) privateviewreturns (bytes32[] memory) {
return set._values;
}
// Bytes32SetstructBytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/functionadd(Bytes32Set storage set, bytes32 value) internalreturns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/functionremove(Bytes32Set storage set, bytes32 value) internalreturns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/functioncontains(Bytes32Set storage set, bytes32 value) internalviewreturns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/functionlength(Bytes32Set storage set) internalviewreturns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/functionat(Bytes32Set storage set, uint256 index) internalviewreturns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/functionvalues(Bytes32Set storage set) internalviewreturns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
/// @solidity memory-safe-assemblyassembly {
result := store
}
return result;
}
// AddressSetstructAddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/functionadd(AddressSet storage set, address value) internalreturns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/functionremove(AddressSet storage set, address value) internalreturns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/functioncontains(AddressSet storage set, address value) internalviewreturns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/functionlength(AddressSet storage set) internalviewreturns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/functionat(AddressSet storage set, uint256 index) internalviewreturns (address) {
returnaddress(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/functionvalues(AddressSet storage set) internalviewreturns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
/// @solidity memory-safe-assemblyassembly {
result := store
}
return result;
}
// UintSetstructUintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/functionadd(UintSet storage set, uint256 value) internalreturns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/functionremove(UintSet storage set, uint256 value) internalreturns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/functioncontains(UintSet storage set, uint256 value) internalviewreturns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values in the set. O(1).
*/functionlength(UintSet storage set) internalviewreturns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/functionat(UintSet storage set, uint256 index) internalviewreturns (uint256) {
returnuint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/functionvalues(UintSet storage set) internalviewreturns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
/// @solidity memory-safe-assemblyassembly {
result := store
}
return result;
}
}
Contract Source Code
File 34 of 124: FeeConditionBase.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;import {OspContext} from'../../core/base/OspContext.sol';
import {CondErrors} from'./libraries/CondErrors.sol';
import {IGovernanceLogic} from'../logics/interfaces/IGovernanceLogic.sol';
/**
* @title FeeConditionBase
* @author OpenSocial Protocol
*
* @dev This is an abstract contract to be inherited from by conditions that require basic fee functionality. It
* contains getters for condition globals parameters as well as a validation function to check expected data.
*/abstractcontractFeeConditionBaseisOspContext{
function_validateDataIsExpected(bytescalldata data,
address currency,
uint256 amount
) internalpure{
(address decodedCurrency, uint256 decodedAmount) =abi.decode(data, (address, uint256));
if (decodedAmount != amount || decodedCurrency != currency)
revert CondErrors.ConditionDataMismatch();
}
function_tokenWhitelisted(address token) internalviewreturns (bool) {
return IGovernanceLogic(OSP).isTokenWhitelisted(token);
}
}
Contract Source Code
File 35 of 124: FixedFeeCommunityCond.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;import {IERC721} from'@openzeppelin/contracts/token/ERC721/IERC721.sol';
import {CommunityCondBase} from'../../base/CommunityCondBase.sol';
import {Payment} from'../../../libraries/Payment.sol';
import {ECDSA} from'@openzeppelin/contracts/utils/cryptography/ECDSA.sol';
import {CondErrors} from'../libraries/CondErrors.sol';
import {CondDataTypes} from'../libraries/CondDataTypes.sol';
import {CondHelpers} from'../libraries/CondHelpers.sol';
/**
* @title FixedFeeCommunityCond
* @author OpenSocial Protocol
*
* @dev This contract specifies that pay the specified amount of ETH to create the community.
* The amount of ETH paid is related to the handle length of the community.
*/contractFixedFeeCommunityCondisCommunityCondBase{
eventFixFeeCondDataSet(CondDataTypes.FixedFeeCondData data, uint256 timestamp);
eventFixFeePaid(addressindexed to, uint256 price, string handle, uint256 timestamp);
CondDataTypes.FixedFeeCondData public fixedFeeCondData;
constructor(address osp) CommunityCondBase(osp) {}
/**
* @dev process create community,if the slotNFT is used, revert.
*/function_processCreateCommunity(address to,
stringcalldata handle,
bytescalldata/*data*/) internaloverride{
/// @dev if createStartTime is not set, indicates no initialization.if (
block.timestamp< fixedFeeCondData.createStartTime ||
fixedFeeCondData.createStartTime ==0
) {
revert CondErrors.NotCreateTime();
}
uint256 price = CondHelpers.getHandleETHPrice(handle, fixedFeeCondData);
_charge(price, to);
emit FixFeePaid(to, price, handle, block.timestamp);
}
functionsetFixedFeeCondData(
CondDataTypes.FixedFeeCondData calldata data
) externalonlyOperation{
fixedFeeCondData = CondDataTypes.FixedFeeCondData({
price1Letter: data.price1Letter,
price2Letter: data.price2Letter,
price3Letter: data.price3Letter,
price4Letter: data.price4Letter,
price5Letter: data.price5Letter,
price6Letter: data.price6Letter,
price7ToMoreLetter: data.price7ToMoreLetter,
createStartTime: data.createStartTime
});
emit FixFeeCondDataSet(data, block.timestamp);
}
/**
* @dev Get the handle price based on the length of the handle.
*/functiongetHandlePrice(stringcalldata handle) externalviewreturns (uint256) {
return CondHelpers.getHandleETHPrice(handle, fixedFeeCondData);
}
function_charge(uint256 price, address to) internalvirtual{
if (msg.value< price) {
revert CondErrors.InsufficientPayment();
}
uint256 overpayment;
unchecked {
overpayment =msg.value- price;
}
if (overpayment >0) {
Payment.payNative(to, overpayment);
}
address treasure = OSP.getTreasureAddress();
require(treasure !=address(0), 'Invalid treasure');
Payment.payNative(treasure, price);
}
}
Contract Source Code
File 36 of 124: FollowSBT.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;import'../interfaces/IFollowSBT.sol';
import'../interfaces/IFollowCondition.sol';
import'./logics/interfaces/OspClient.sol';
import'../libraries/OspErrors.sol';
import'../libraries/OspEvents.sol';
import'./base/OspSBTBase.sol';
/**
* @title FollowSBT
* @author OpenSocial Protocol
* @dev This contract is the NFT that is minted upon following a given profile. It is cloned upon first follow for a
* given profile.
*/contractFollowSBTisOspSBTBase, IFollowSBT{
addresspublicimmutable OSP;
uint256internal _profileId;
uint256internal _tokenIdCounter;
// We create the FollowSBT with the pre-computed OSP address before deploying the osp.constructor(address osp) {
if (osp ==address(0)) revert OspErrors.InitParamsInvalid();
OSP = osp;
}
/// @inheritdoc IFollowSBTfunctioninitialize(uint256 profileId,
stringcalldata name,
stringcalldata symbol
) externaloverride{
if (msg.sender!= OSP) revert OspErrors.NotOSP();
_profileId = profileId;
super._initialize(name, symbol);
emit OspEvents.FollowSBTInitialized(profileId, block.timestamp);
}
/// @inheritdoc IFollowSBTfunctionmint(address to) externaloverridereturns (uint256) {
if (msg.sender!= OSP) revert OspErrors.NotOSP();
unchecked {
uint256 tokenId =++_tokenIdCounter;
_mint(to, tokenId);
return tokenId;
}
}
/**
* @dev This returns the follow NFT URI fetched from the osp.
*/functiontokenURI(uint256 tokenId) publicviewoverridereturns (stringmemory) {
return OspClient(OSP).getFollowSBTURI(_profileId, tokenId);
}
/**
* @dev Upon transfers, we move the appropriate delegations, and emit the transfer event in the osp.
*/function_afterTokenTransfer(addressfrom, address to, uint256 tokenId) internaloverride{
super._afterTokenTransfer(from, to, tokenId);
OspClient(OSP).emitFollowSBTTransferEvent(_profileId, tokenId, from, to);
}
}
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;import {CondErrors} from'../libraries/CondErrors.sol';
import {JoinConditionBase} from'../../base/JoinConditionBase.sol';
/**
* @title HoldTokenJoinCond
* @param token token address,if token is address(0) means native token.
* @param amount token amount.
*/structCommunityData {
address token;
uint256 amount;
}
/**
* @title IToken
* @dev Used to check erc20 or erc721 token balance
*/interfaceIToken{
functionbalanceOf(address owner) externalviewreturns (uint256);
}
/**
* @title HoldTokenJoinCond
* @author OpenSocial
* @dev This condition allows users to join a community by holding a certain amount of tokens.
*/contractHoldTokenJoinCondisJoinConditionBase{
mapping(uint256=> CommunityData) _dataByCommunity;
constructor(address osp) JoinConditionBase(osp) {}
function_initializeCommunityJoinCondition(uint256 communityId,
bytescalldata data
) internaloverride{
(address _token, uint256 _amount) =abi.decode(data, (address, uint256));
_dataByCommunity[communityId].token = _token;
_dataByCommunity[communityId].amount = _amount;
}
function_processJoin(address joiner,
uint256 communityId,
bytescalldata data
) internaloverridenonPayable{
(data); //unusedaddress token = _dataByCommunity[communityId].token;
if (token ==address(0) && joiner.balance>= _dataByCommunity[communityId].amount) {
//native tokenreturn;
} elseif (
token !=address(0) &&
IToken(token).balanceOf(joiner) >= _dataByCommunity[communityId].amount
) {
//ERC20 or ERC721 tokenreturn;
}
revert CondErrors.JoinInvalid();
}
function_processTransferJoinNFT(uint256 communityId,
uint256 joinNFTId,
addressfrom,
address to
) internaloverride{
if (from!=address(0) && to !=address(0)) {
revert CondErrors.JoinNFTTransferInvalid();
}
}
/**
* @dev Returns the community data for a given community, or an empty struct if that community was not initialized
* with this condition.
*/functiongetCommunityData(uint256 communityId) externalviewreturns (CommunityData memory) {
return _dataByCommunity[communityId];
}
}
Contract Source Code
File 42 of 124: IAccessControl.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)pragmasolidity ^0.8.20;/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/interfaceIAccessControl{
/**
* @dev The `account` is missing a role.
*/errorAccessControlUnauthorizedAccount(address account, bytes32 neededRole);
/**
* @dev The caller of a function is not the expected one.
*
* NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
*/errorAccessControlBadConfirmation();
/**
* @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.
*/eventRoleAdminChanged(bytes32indexed role, bytes32indexed previousAdminRole, bytes32indexed 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}.
*/eventRoleGranted(bytes32indexed role, addressindexed account, addressindexed 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`)
*/eventRoleRevoked(bytes32indexed role, addressindexed account, addressindexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/functionhasRole(bytes32 role, address account) externalviewreturns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/functiongetRoleAdmin(bytes32 role) externalviewreturns (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.
*/functiongrantRole(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.
*/functionrevokeRole(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`.
*/functionrenounceRole(bytes32 role, address callerConfirmation) external;
}
Contract Source Code
File 43 of 124: IActivityCondition.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;/**
* @title IActivityCondition
* @author Osp Protocol
*
* @dev This is the standard interface for all Osp-compatible ActivityConditions.
*/interfaceIActivityCondition{
/**
* @dev Initializes a post Condition for a given OSP community. This can only be called by the osp contract.
*
* @param communityId The token ID of the community to initialize this post condition for.
* @param data initialization data.
*/functioninitializeCommunityActivityCondition(uint256 communityId,
bytescalldata data
) external;
/**
* @dev Processes a given post, this can only be called from the OSP contract.
*
* @param communityId The token ID of the community being posted to.
* @param profileId The token ID of the profile being posted.
*/functionprocessActivity(uint256 communityId, address profileOwner, uint256 profileId) external;
}
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol)pragmasolidity ^0.8.20;/**
* @dev This is the interface that {BeaconProxy} expects of its beacon.
*/interfaceIBeacon{
/**
* @dev Must return an address that can be used as a delegate call target.
*
* {UpgradeableBeacon} will check that this address is a contract.
*/functionimplementation() externalviewreturns (address);
}
Contract Source Code
File 47 of 124: ICommunityCondition.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;/**
* @title ICommunityCondition
* @author Opensocial Protocol
*
* @dev This is the standard interface for all Osp-compatible Conditions.
* Conditions are used to check if a community can be created.
*/interfaceICommunityCondition{
/**
* @dev Checks if a community can be created.
* @param to community creator.
* @param data condition data for checking.
*/functionprocessCreateCommunity(address to,
stringcalldata handle,
bytescalldata data
) externalpayable;
}
Contract Source Code
File 48 of 124: ICommunityLogic.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;import'../../../libraries/OspDataTypes.sol';
/**
* @title ICommunityLogic
* @author OpenSocial Protocol
*
* @dev This is the interface for the ICommunityLogic contract.
*/interfaceICommunityLogic{
/**
* @dev Creates a community with the specified parameters, minting a community NFT to the msg sender.
*
* @param vars A CreateCommunityData struct containing the needed parameters.
*
* @return uint256 An integer representing the community's ID.
*/functioncreateCommunity(
OspDataTypes.CreateCommunityData calldata vars
) externalpayablereturns (uint256);
/**
* @dev Creates a community and set activity condition, minting a community NFT to the msg sender.
*
* @param vars A CreateCommunityData struct containing the needed parameters.
* @param activityConditionInitCode The data to be passed to the activity condition for initialization.
* @param viewPrivacyConditionInitCode The data to be passed to the view privacy condition for initialization.
*
* @return uint256 An integer representing the community's ID.
*/functioncreateCommunity(
OspDataTypes.CreateCommunityData calldata vars,
bytescalldata activityConditionInitCode,
bytescalldata viewPrivacyConditionInitCode
) externalpayablereturns (uint256);
/**
* @dev Sets a community's join condition, must be called by the community owner or admin.
* @param communityId The ID of the community to set the join condition for.
* @param joinConditionInitCode The data to be passed to the join condition for initialization.
*/functionsetJoinCondition(uint256 communityId, bytescalldata joinConditionInitCode) external;
/**
* @dev Sets a community's activity condition, must be called by the community owner or admin.
* @param communityId The ID of the community to set the activity condition for.
* @param activityConditionInitCode The data to be passed to the activity condition for initialization.
*/functionsetActivityCondition(uint256 communityId,
bytescalldata activityConditionInitCode
) external;
/**
* @dev Sets a community's view privacy condition, must be called by the community owner or admin.
* @param communityId The ID of the community to set the view privacy condition for.
* @param viewPrivacyConditionInitCode The data to be passed to the view privacy condition for initialization.
*/functionsetViewPrivacyCondition(uint256 communityId,
bytescalldata viewPrivacyConditionInitCode
) external;
/**
* @dev Checks if a profile is allowed to view a community privacy content, based on the view privacy condition.
* @param communityId The ID of the community to check.
* @param profileId The ID of the profile to check.
* @return bool A boolean indicating whether the profile is allowed to view the community privacy content or not.
*/functionisViewPrivacyAllowed(uint256 communityId,
uint256 profileId
) externalviewreturns (bool);
/**
* @dev Updates a community's tags, must be called by the community owner or admin.
* @param communityId The ID of the community to set the tags for.
* @param tags The new tags for the community.
*/functionupdateTags(uint256 communityId, string[] calldata tags) external;
/**
* @dev Sets a community's extension whitelist, must be called by the community owner or admin.
* @param communityId The ID of the community to set the extension whitelist for.
* @param extension The address of the extension to whitelist.
* @param isWhitelist A boolean indicating whether the extension should be whitelisted or not.
*/functionsetCommunityActivityExtensionWhitelist(uint256 communityId,
address extension,
bool isWhitelist
) external;
/**
* @dev emits a CommunityNFTTransfer event to facilitate the monitoring of events.
*
* @param communityId is CommunityNFT being transferred's token ID.
* @param from The address the collectNFT is being transferred from.
* @param to The address the collectNFT is being transferred to.
*/functionemitCommunityNFTTransferEvent(uint256 communityId, addressfrom, address to) external;
/**
* @dev Returns the struct with a community.
*
* @param communityId The ID of the community.
*
* @return string The struct of community.
*/functiongetCommunity(uint256 communityId
) externalviewreturns (OspDataTypes.CommunityStruct memory);
/**
* @dev Returns the joinNFT associated with a given community, if any.
* @param communityId The unique ID of the community to query the joinNFT for.
* @return address The joinNFT associated with the given profile.
*/functiongetJoinNFT(uint256 communityId) externalviewreturns (address);
/**
* @dev Returns the join condition associated witha given community, if any.
* @param communityId The unique ID of the community to query the join condition for.
* @return address The address of the join condition associated with the given community.
*/functiongetJoinCondition(uint256 communityId) externalviewreturns (address);
/**
* @dev Returns the activity condition associated witha given community, if any.
* @param communityId The unique ID of the community to query the activity condition for.
* @return address The address of the activity condition associated with the given community.
*/functiongetActivityCondition(uint256 communityId) externalviewreturns (address);
/**
* @dev Returns the tokenURI associated with a given community, if any.
*
* @param communityId The unique ID of the community to query the tokenURI for.
* @return string The tokenURI associated with the given community.
*/functiongetCommunityTokenURI(uint256 communityId) externalviewreturns (stringmemory);
/**
* @dev Returns the community ID associated with a given community handle, if any.
*
* @param handle The handle of the community to query the ID for.
* @return uint256 The ID of the community associated with the given handle.
*/functiongetCommunityIdByHandle(stringcalldata handle) externalviewreturns (uint256);
/**
* @dev Returns community nft 6551 account address.
* @param communityId community nft token id
*/functiongetCommunityAccount(uint256 communityId) externalviewreturns (address);
/**
* @dev Returns community nft 6551 account address.
* @param handle community handle.
*/functiongetCommunityAccount(stringcalldata handle) externalviewreturns (address);
/**
* @dev Returns the extension whitelist associated with a given community, if any.
* @param communityId The unique ID of the community to query the extension whitelist for.
*/functiongetCommunityActivityExtensionWhitelist(uint256 communityId
) externalviewreturns (address[] memory extensions);
}
Contract Source Code
File 49 of 124: ICommunityNFT.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;/**
* @title ICommunityNFT
* @author OpenSocial Protocol
*
* @dev This is the standard interface for all OSP-compatible CollectConditions.
*/interfaceICommunityNFT{
/**
* @dev Mints a collect NFT to the specified address. This can only be called by the osp;
*
* @param to The address to mint the NFT to.
*
* @return uint256 An interger representing the minted token ID.
*/functionmint(address to) externalreturns (uint256);
/**
* @dev updates the metadata for the NFT.
*/functionupdateMetadata() external;
}
Contract Source Code
File 50 of 124: ICompositeActivityCond.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;import {IActivityCondition} from'contracts/interfaces/IActivityCondition.sol';
/**
* @title ICompositeActivityCond
* @dev This contract allows for the creation of composite activity conditions,
* which can be used to combine multiple activity conditions using logical operators.
*/interfaceICompositeActivityCondisIActivityCondition{
/**
* @dev Enum representing the available logical operators for combining activity conditions.
*/enumOperatorEnum {
AND,
OR
}
/**
* @dev Struct representing the composite activity condition data.
* @param operator The logical operator used to combine the activity conditions.
* @param conditions The array of activity conditions to be combined.
*/structCompositeData {
OperatorEnum operator;
IActivityCondition[] conditions;
}
/**
* @dev Returns the composite activity condition data for the specified community.
* @param communityId The ID of the community.
* @return The composite activity condition data.
*/functiongetCompositeData(uint256 communityId) externalviewreturns (CompositeData memory);
}
Contract Source Code
File 51 of 124: ICompositeViewPrivacyCond.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;import {IViewPrivacyCondition} from'contracts/interfaces/IViewPrivacyCondition.sol';
/**
* @title ICompositeViewPrivacyCond.sol
* @dev This contract allows for the creation of composite privacy conditions,
* which are combinations of other privacy conditions.
*/interfaceICompositeViewPrivacyCondisIViewPrivacyCondition{
/**
* @dev Enum representing the available logical operators for combining view privacy conditions.
*/enumOperatorEnum {
AND,
OR
}
/**
* @dev Struct representing the composite view privacy condition data.
* @param operator The logical operator used to combine the conditions.
* @param conditions The array of view privacy conditions to be combined.
*/structCompositeData {
OperatorEnum operator;
IViewPrivacyCondition[] conditions;
}
/**
* @dev Returns the composite view privacy condition data for a given community.
* @param communityId The ID of the community.
* @return The composite view privacy condition data.
*/functiongetCompositeData(uint256 communityId) externalviewreturns (CompositeData memory);
}
Contract Source Code
File 52 of 124: IContentLogic.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;import'../../../libraries/OspDataTypes.sol';
/**
* @title IContentLogic
* @author OpenSocial Protocol
*
* @dev This is the interface for the ContentLogic contract.
*/interfaceIContentLogic{
/**
* @dev Create an activity.
*
* @param vars A CreateActivityData struct.
*
* @return contentId Activity's content ID.
*/functioncreateActivity(
OspDataTypes.CreateActivityData calldata vars
) externalpayablereturns (uint256 contentId);
/**
* @dev Create an activity with a signature.
*
* @param vars A CreateActivityData struct.
* @param sig A EIP712Signature struct.
*
* @return contentId Activity's content ID.
*/functioncreateActivityWithSig(
OspDataTypes.CreateActivityData calldata vars,
OspDataTypes.EIP712Signature calldata sig
) externalreturns (uint256 contentId);
/**
* @dev Create a comment.
*
* @param vars A CreateCommentData struct.
*
* @return contentId Comment's content ID.
*/functioncreateComment(
OspDataTypes.CreateCommentData calldata vars
) externalpayablereturns (uint256 contentId);
/**
* @dev Create a comment with a signature.
*
* @param vars A CreateCommentData struct.
* @param sig A EIP712Signature struct.
*
* @return contentId Comment's content ID.
*/functioncreateCommentWithSig(
OspDataTypes.CreateCommentData calldata vars,
OspDataTypes.EIP712Signature calldata sig
) externalreturns (uint256 contentId);
/**
* @dev Create an open reaction.
*
* @param vars A CreateOpenReactionData struct.
*/functioncreateOpenReaction(OspDataTypes.CreateOpenReactionData calldata vars) externalpayable;
/**
* @dev Create an open reaction with a signature.
*
* @param vars A CreateOpenReactionData struct.
* @param sig A EIP712Signature struct.
*/functioncreateOpenReactionWithSig(
OspDataTypes.CreateOpenReactionData calldata vars,
OspDataTypes.EIP712Signature calldata sig
) external;
/**
* @dev Create a megaphone.
*
* @param vars A CreateMegaphoneData struct.
*
* @return megaphoneId Megaphone's ID.
*/functioncreateMegaphone(
OspDataTypes.CreateMegaphoneData calldata vars
) externalpayablereturns (uint256 megaphoneId);
/// ************************/// *****VIEW FUNCTIONS*****/// ************************/**
* @dev Returns the content count for a given profile.
*
* @param profileId The profile ID to query.
*
* @return uint256 Content count for the given profile.
*/functiongetContentCount(uint256 profileId) externalviewreturns (uint256);
/**
* @dev Returns the content struct for a given content.
*
* @param profileId The profile ID that published the content to query.
* @param contentId The content ID of the content to query.
*
* @return ContentStruct The content struct associated with the queried content.
*/functiongetContent(uint256 profileId,
uint256 contentId
) externalviewreturns (OspDataTypes.ContentStruct memory);
/**
* @dev Returns the community's ID by content.
*
* @param profileId The profile ID that published the content to query.
* @param contentId The content ID of the content to query.
*
* @return uint256 community's ID.
*/functiongetCommunityIdByContent(uint256 profileId,
uint256 contentId
) externalviewreturns (uint256);
}
Contract Source Code
File 53 of 124: IContractMetadata.sol
// SPDX-License-Identifier: Apache-2.0pragmasolidity ^0.8.0;/// @author thirdweb/**
* Thirdweb's `ContractMetadata` is a contract extension for any base contracts. It lets you set a metadata URI
* for you contract.
*
* Additionally, `ContractMetadata` is necessary for NFT contracts that want royalties to get distributed on OpenSea.
*/interfaceIContractMetadata{
/// @dev Returns the metadata URI of the contract.functioncontractURI() externalviewreturns (stringmemory);
/**
* @dev Sets contract URI for the storefront-level metadata of the contract.
* Only module admin can call this function.
*/functionsetContractURI(stringcalldata _uri) external;
/// @dev Emitted when the contract URI is updated.eventContractURIUpdated(string prevURI, string newURI);
}
Contract Source Code
File 54 of 124: IERC1155Receiver.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/IERC1155Receiver.sol)pragmasolidity ^0.8.20;import {IERC165} from"../../utils/introspection/IERC165.sol";
/**
* @dev Interface that must be implemented by smart contracts in order to receive
* ERC-1155 token transfers.
*/interfaceIERC1155ReceiverisIERC165{
/**
* @dev Handles the receipt of a single ERC1155 token type. This function is
* called at the end of a `safeTransferFrom` after the balance has been updated.
*
* NOTE: To accept the transfer, this must return
* `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
* (i.e. 0xf23a6e61, or its own function selector).
*
* @param operator The address which initiated the transfer (i.e. msg.sender)
* @param from The address which previously owned the token
* @param id The ID of the token being transferred
* @param value The amount of tokens being transferred
* @param data Additional data with no specified format
* @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
*/functiononERC1155Received(address operator,
addressfrom,
uint256 id,
uint256 value,
bytescalldata data
) externalreturns (bytes4);
/**
* @dev Handles the receipt of a multiple ERC1155 token types. This function
* is called at the end of a `safeBatchTransferFrom` after the balances have
* been updated.
*
* NOTE: To accept the transfer(s), this must return
* `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
* (i.e. 0xbc197c81, or its own function selector).
*
* @param operator The address which initiated the batch transfer (i.e. msg.sender)
* @param from The address which previously owned the token
* @param ids An array containing ids of each token being transferred (order and length must match values array)
* @param values An array containing amounts of each token being transferred (order and length must match ids array)
* @param data Additional data with no specified format
* @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
*/functiononERC1155BatchReceived(address operator,
addressfrom,
uint256[] calldata ids,
uint256[] calldata values,
bytescalldata data
) externalreturns (bytes4);
}
Contract Source Code
File 55 of 124: IERC1271.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1271.sol)pragmasolidity ^0.8.20;/**
* @dev Interface of the ERC1271 standard signature validation method for
* contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].
*/interfaceIERC1271{
/**
* @dev Should return whether the signature provided is valid for the provided data
* @param hash Hash of the data to be signed
* @param signature Signature byte array associated with _data
*/functionisValidSignature(bytes32 hash, bytesmemory signature) externalviewreturns (bytes4 magicValue);
}
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)pragmasolidity ^0.8.20;/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/interfaceIERC20{
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/eventTransfer(addressindexedfrom, addressindexed 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.
*/eventApproval(addressindexed owner, addressindexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/functiontotalSupply() externalviewreturns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/functionbalanceOf(address account) externalviewreturns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/functiontransfer(address to, uint256 value) externalreturns (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.
*/functionallowance(address owner, address spender) externalviewreturns (uint256);
/**
* @dev Sets a `value` amount of tokens 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.
*/functionapprove(address spender, uint256 value) externalreturns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/functiontransferFrom(addressfrom, address to, uint256 value) externalreturns (bool);
}
Contract Source Code
File 58 of 124: IERC20Permit.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)pragmasolidity ^0.8.20;/**
* @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.
*/interfaceIERC20Permit{
/**
* @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.
*/functionpermit(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.
*/functionnonces(address owner) externalviewreturns (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-mixedcasefunctionDOMAIN_SEPARATOR() externalviewreturns (bytes32);
}
Contract Source Code
File 59 of 124: IERC2981.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC2981.sol)pragmasolidity ^0.8.20;import {IERC165} from"../utils/introspection/IERC165.sol";
/**
* @dev Interface for the NFT Royalty Standard.
*
* A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal
* support for royalty payments across all NFT marketplaces and ecosystem participants.
*/interfaceIERC2981isIERC165{
/**
* @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of
* exchange. The royalty amount is denominated and should be paid in that same unit of exchange.
*/functionroyaltyInfo(uint256 tokenId,
uint256 salePrice
) externalviewreturns (address receiver, uint256 royaltyAmount);
}
Contract Source Code
File 60 of 124: IERC4906.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;/// @title EIP-721 Metadata Update ExtensioninterfaceIERC4906{
/// @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.eventMetadataUpdate(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.eventBatchMetadataUpdate(uint256 _fromTokenId, uint256 _toTokenId);
}
Contract Source Code
File 61 of 124: IERC5267.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol)pragmasolidity ^0.8.20;interfaceIERC5267{
/**
* @dev MAY be emitted to signal that the domain could have changed.
*/eventEIP712DomainChanged();
/**
* @dev returns the fields and values that describe the domain separator used by this contract for EIP-712
* signature.
*/functioneip712Domain()
externalviewreturns (bytes1 fields,
stringmemory name,
stringmemory version,
uint256 chainId,
address verifyingContract,
bytes32 salt,
uint256[] memory extensions
);
}
Contract Source Code
File 62 of 124: IERC6551Registry.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;interfaceIERC6551Registry{
/**
* @dev The registry MUST emit the ERC6551AccountCreated event upon successful account creation.
*/eventERC6551AccountCreated(address account,
addressindexed implementation,
bytes32 salt,
uint256 chainId,
addressindexed tokenContract,
uint256indexed tokenId
);
/**
* @dev The registry MUST revert with AccountCreationFailed error if the create2 operation fails.
*/errorAccountCreationFailed();
/**
* @dev Creates a token bound account for a non-fungible token.
*
* If account has already been created, returns the account address without calling create2.
*
* Emits ERC6551AccountCreated event.
*
* @return account The address of the token bound account
*/functioncreateAccount(address implementation,
bytes32 salt,
uint256 chainId,
address tokenContract,
uint256 tokenId
) externalreturns (address account);
/**
* @dev Returns the computed token bound account address for a non-fungible token.
*
* @return account The address of the token bound account
*/functionaccount(address implementation,
bytes32 salt,
uint256 chainId,
address tokenContract,
uint256 tokenId
) externalviewreturns (address account);
}
Contract Source Code
File 63 of 124: IERC721.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721.sol)pragmasolidity ^0.8.20;import {IERC165} from"../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/interfaceIERC721isIERC165{
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/eventTransfer(addressindexedfrom, addressindexed to, uint256indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/eventApproval(addressindexed owner, addressindexed approved, uint256indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/eventApprovalForAll(addressindexed owner, addressindexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/functionbalanceOf(address owner) externalviewreturns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/functionownerOf(uint256 tokenId) externalviewreturns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
* a safe transfer.
*
* Emits a {Transfer} event.
*/functionsafeTransferFrom(addressfrom, address to, uint256 tokenId, bytescalldata data) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or
* {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
* a safe transfer.
*
* Emits a {Transfer} event.
*/functionsafeTransferFrom(addressfrom, address to, uint256 tokenId) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
* or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
* understand this adds an external call which potentially creates a reentrancy vulnerability.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/functiontransferFrom(addressfrom, address to, uint256 tokenId) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/functionapprove(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the address zero.
*
* Emits an {ApprovalForAll} event.
*/functionsetApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/functiongetApproved(uint256 tokenId) externalviewreturns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/functionisApprovedForAll(address owner, address operator) externalviewreturns (bool);
}
Contract Source Code
File 64 of 124: IERC721Burnable.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;import {IERC721} from'@openzeppelin/contracts/token/ERC721/IERC721.sol';
/**
* @title IERC721Burnable
* @author OpenSocial Protocol
* @dev This is the interface for all ERC721Burnable contracts.
*/interfaceIERC721BurnableisIERC721{
/**
* @dev Burns an NFT, removing it from circulation and essentially destroying it. This function can only
* be called by the NFT to burn's owner.
*
* @param tokenId The token ID of the token to burn.
*/functionburn(uint256 tokenId) external;
}
Contract Source Code
File 65 of 124: IERC721Enumerable.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Enumerable.sol)pragmasolidity ^0.8.20;import {IERC721} from"../IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/interfaceIERC721EnumerableisIERC721{
/**
* @dev Returns the total amount of tokens stored by the contract.
*/functiontotalSupply() externalviewreturns (uint256);
/**
* @dev Returns a token ID owned by `owner` at a given `index` of its token list.
* Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
*/functiontokenOfOwnerByIndex(address owner, uint256 index) externalviewreturns (uint256);
/**
* @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
* Use along with {totalSupply} to enumerate all tokens.
*/functiontokenByIndex(uint256 index) externalviewreturns (uint256);
}
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721Receiver.sol)pragmasolidity ^0.8.20;/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/interfaceIERC721Receiver{
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be
* reverted.
*
* The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
*/functiononERC721Received(address operator,
addressfrom,
uint256 tokenId,
bytescalldata data
) externalreturns (bytes4);
}
Contract Source Code
File 68 of 124: IFollowCondition.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;/**
* @title IFollowCondition
* @author OpenSocial Protocol
*
* @dev This is the standard interface for all OSP-compatible FollowConditions.
*/interfaceIFollowCondition{
/**
* @dev Initializes a follow Condition for a given OSP profile. This can only be called by the osp contract.
*
* @param profileId The token ID of the profile to initialize this follow condition for.
* @param data initialization data.
*/functioninitializeFollowCondition(uint256 profileId, bytescalldata data) external;
/**
* @dev Processes a given follow, this can only be called from the OSP contract.
*
* @param follower The follower address.
* @param profileId The token ID of the profile being followed.
* @param data data for processing.
*/functionprocessFollow(address follower,
uint256 profileId,
bytescalldata data
) externalpayable;
}
Contract Source Code
File 69 of 124: IFollowSBT.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;/**
* @title IFollowSBT
* @author OpenSocial Protocol
*
* @dev This is the interface for the FollowSBT contract, which is cloned upon the first follow for any profile.
*/interfaceIFollowSBT{
/**
* @dev Initializes the follow NFT, setting the osp as the privileged minter and storing the associated profile ID.
*
* @param profileId The token ID of the profile in the osp associated with this FollowSBT, used for transfer hooks.
* @param name The name to set for this NFT.
* @param symbol The symbol to set for this NFT.
*/functioninitialize(uint256 profileId, stringcalldata name, stringcalldata symbol) external;
/**
* @dev Mints a follow NFT to the specified address. This can only be called by the osp, and is called
* upon follow.
*
* @param to The address to mint the NFT to.
*
* @return uint256 An interger representing the minted token ID.
*/functionmint(address to) externalreturns (uint256);
}
Contract Source Code
File 70 of 124: IGovernanceLogic.sol
// SPDX-License-Identifier: MITpragmasolidity 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';
import'@thirdweb-dev/contracts/extension/interface/IContractMetadata.sol';
/**
* @title IGovernanceLogic
* @author OpenSocial Protocol
*
* @dev This is the interface for the GovernanceLogic contract.
*/interfaceIGovernanceLogicisIERC4906, IERC5267, IAccessControl, IContractMetadata{
/**
* @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.
*/functioninitialize(stringcalldata name,
stringcalldata 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.
*/functionsetState(OspDataTypes.ProtocolState newState) 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.
*/functionwhitelistApp(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
*/functionwhitelistToken(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.
*/functionreserveCommunityHandle(stringcalldata 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.
*/functionsetBaseURI(stringcalldata baseURI) external;
functionsetERC6551AccountImpl(address accountImpl) external;
functionsetJoinNFTImpl(address joinNFTImpl) external;
/// ************************/// *****VIEW FUNCTIONS*****/// ************************functionisAppWhitelisted(address app) externalviewreturns (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.
*/functionisTokenWhitelisted(address token) externalviewreturns (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.
*/functionisReserveCommunityHandle(stringcalldata handle) externalviewreturns (bool);
/**
* @dev Returns the base URI for the NFTs.
*
* @return string The base URI for the NFTs.
*/functiongetBaseURI() externalviewreturns (stringmemory);
/**
* @dev Returns the follow NFT implementation address.
*
* @return address The follow NFT implementation address.
*/functiongetFollowSBTImpl() externalviewreturns (address);
/**
* @dev Returns the join NFT implementation address.
*
* @return address The join NFT implementation address.
*/functiongetJoinNFTImpl() externalviewreturns (address);
/**
* @dev Returns the community NFT address.
*
* @return address The community NFT address.
*/functiongetCommunityNFT() externalviewreturns (address);
functiongetERC6551AccountImpl() externalviewreturns (address);
/**
* @dev Returns the current protocol state.
*
* @return ProtocolState The Protocol state, an enum, where:
* 0: Unpaused
* 1: PublishingPaused
* 2: Paused
*/functiongetState() externalviewreturns (OspDataTypes.ProtocolState);
functionupdateMetadata() external;
/**
* @dev Update The treasure address.This function can only be called by the current governance.
*/functionsetTreasureAddress(address treasure) external;
/**
* @dev Get The treasure address.
*/functiongetTreasureAddress() externalviewreturns (address);
/**
* @dev Set the royalty fee for the join NFT.
*/functionsetJoinNFTRoyalty(uint128 royaltyFraction, uint128 ospTreasureFraction) external;
functionjoinNFTRoyaltyInfo()
externalviewreturns (uint128 royaltyFraction, uint128 ospTreasureFraction);
}
Contract Source Code
File 71 of 124: IHoldERC721ActivityCond.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;import {IActivityCondition} from'contracts/interfaces/IActivityCondition.sol';
/**
* @title IHoldERC721ActivityCond
* @dev You can only post if you have a specified ERC721 token.
*/interfaceIHoldERC721ActivityCondisIActivityCondition{
/**
* @dev Struct to hold the data for the HoldERC721ActivityCond contract.
* @param tokenAddress The address of the ERC721 token.
* @param amount The min amount of the ERC721 token required.
*/structHoldERC721Data {
address tokenAddress;
uint96 amount;
}
/**
* @dev Returns the HoldERC721Data struct for the specified communityId.
* @param communityId The ID of the community.
* @return The HoldERC721Data struct.
*/functiongetHoldERC721Data(uint256 communityId) externalviewreturns (HoldERC721Data memory);
}
Contract Source Code
File 72 of 124: IHoldERC721ViewPrivacyCond.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;import {IViewPrivacyCondition} from'contracts/interfaces/IViewPrivacyCondition.sol';
/**
* @title IHoldERC721ViewPrivacyCond
* @dev You can only view privacy if you have a specified ERC721 token.
*/interfaceIHoldERC721ViewPrivacyCondisIViewPrivacyCondition{
/**
* @dev Struct to hold the data for the HoldERC721ActivityCond contract.
* @param tokenAddress The address of the ERC721 token.
* @param amount The amount of the ERC721 token required.
*/structHoldERC721Data {
address tokenAddress;
uint96 amount;
}
/**
* @dev Returns the HoldERC721Data struct for the specified communityId.
* @param communityId The ID of the community.
* @return The HoldERC721Data struct.
*/functiongetHoldERC721Data(uint256 communityId) externalviewreturns (HoldERC721Data memory);
}
Contract Source Code
File 73 of 124: IJoinCondition.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;/**
* @title IJoinCondition
* @author Osp Protocol
*
* @dev This is the standard interface for all Osp-compatible JoinConditions.
*/interfaceIJoinCondition{
/**
* @dev Initializes a join Condition for a given OSP community. This can only be called by the osp contract.
*
* @param communityId The token ID of the community to initialize this join condition for.
* @param data initialization data.
*/functioninitializeCommunityJoinCondition(uint256 communityId, bytescalldata data) external;
/**
* @dev Processes a given join, this can only be called from the OSP contract.
*
* @param joiner The joiner address.
* @param community The token ID of the community being joined.
* @param data data for processing.
*/functionprocessJoin(address joiner, uint256 community, bytescalldata data) externalpayable;
functionprocessTransferJoinNFT(uint256 communityId,
uint256 joinNFTId,
addressfrom,
address to
) external;
}
Contract Source Code
File 74 of 124: IJoinNFT.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;/**
* @title IJoinNFT
* @author OpenSocial Protocol
*
* @dev This is the interface for the JoinNFT contract. Deploy this NFT contract when creating the community
*/interfaceIJoinNFT{
/**
* @dev Initializes the Join NFT, setting the feed as the privileged minter, storing the collected content pointer
* and initializing the name and symbol in the OspNFTBase contract.
*
* @param communityId The community unique ID this JoinNFT points to.
* @param name The name to set for this NFT.
* @param symbol The symbol to set for this NFT.
*/functioninitialize(uint256 communityId, stringcalldata name, stringcalldata symbol) external;
/**
* @dev Mints a join NFT to the specified address. This can only be called by the osp, and is called
* upon collection.
*
* @param to The address to mint the NFT to.
*
* @return uint256 An interger representing the minted token ID.
*/functionmint(address to) externalreturns (uint256);
/**
* @dev Sets the admin role for the specified account.
*
* @param account The account to set the admin role for.
*
* @return bool A boolean indicating whether the operation was successful.
*/functionsetAdmin(address account) externalreturns (bool);
/**
* @dev Sets the mods role for the specified account.
*
* @param account The account to set the mods role for.
*
* @return bool A boolean indicating whether the operation was successful.
*/functionsetModerator(address account) externalreturns (bool);
/**
* @dev Removes the specified role from the specified account.
*
* @param account The account to remove the role.
*
* @return bool A boolean indicating whether the operation was successful.
*/functionremoveRole(address account) externalreturns (bool);
/**
* @dev Sets the member level for the specified account.
*
* @param account The address to set the member level for.
* @param level The level to set for the account.
*
* @return bool A boolean indicating whether the operation was successful.
*/functionsetMemberLevel(address account, uint256 level) externalreturns (bool);
/**
* @dev Adds or removes the specified account from the block list.
*
* @param account The account to add or remove from the block list.
* @param enable A boolean indicating whether to add or remove the account from the block list.
*
* @return bool A boolean indicating whether the operation was successful.
*/functionsetBlockList(address account, bool enable) externalreturns (bool);
/**
* @dev Returns the source community pointer mapped to this collect NFT.
*
* @return communityId.
*/functiongetSourceCommunityPointer() externalviewreturns (uint256);
/**
* @dev Returns `true` if `account` has been granted the `role`.
*/functionhasRole(uint256 roles, address account) externalviewreturns (bool);
/**
* @dev Returns the role of the account.
*/functiongetRole(address account) externalviewreturns (uint256);
/**
* @dev Returns the member level of the account.
*/functiongetMemberLevel(address account) externalviewreturns (uint256);
/**
* @dev Returns the member level of the tokenId.
*/functiongetMemberLevel(uint256 tokenId) externalviewreturns (uint256);
/**
* @dev Returns the block status of the account.
*/functionisBlock(address account) externalviewreturns (bool);
}
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;import'../../../libraries/OspDataTypes.sol';
import'../../../interfaces/IERC721Burnable.sol';
import {IERC721Metadata} from'@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol';
import {IERC721Enumerable} from'@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol';
import {IERC165} from'@openzeppelin/contracts/utils/introspection/IERC165.sol';
/**
* @title IProfileLogic
* @author OpenSocial Protocol
*
* @dev This is the interface for the ProfileLogic contract.
*/interfaceIProfileLogicisIERC721Burnable, IERC721Metadata, IERC721Enumerable{
/**
* @dev Create a Profile for the message sender,each address can only be created once。
*
* @param vars A CreateProfileData struct containing the following params:
* handle: The handle to set for the profile, must be unique and non-empty,can only consist of lowercase letters, numbers and underscores
* followCondition: The follow condition to use, can be the zero address.
* followConditionInitData: The follow condition initialization data, if any.
*
* @return uint256 The token ID of the created profile.
*/functioncreateProfile(OspDataTypes.CreateProfileData calldata vars) externalreturns (uint256);
/**
* @dev Sets a profile's follow condition, must be called by the profile owner.
*
* @param profileId The token ID of the profile to set the follow condition for.
* @param followConditionInitCode The data to be passed to the follow condition for initialization.
*/functionsetFollowCondition(uint256 profileId, bytescalldata followConditionInitCode) external;
/// ************************/// *****VIEW FUNCTIONS*****/// ************************/**
* @dev Returns the FollowSBT of the profile.
*
* @param profileId The profile id to query.
*
* @return address Profile's FollowSBT address.
*/functiongetFollowSBT(uint256 profileId) externalviewreturns (address);
/**
* @dev Returns the follow condition of the profile.
*
* @param profileId The profile id to query.
*
* @return address Profile's follow condition address.
*/functiongetFollowCondition(uint256 profileId) externalviewreturns (address);
/**
* @dev Returns the handle of the profile.
*
* @param profileId The profile id to query.
*
* @return string Profile's handle.
*/functiongetHandle(uint256 profileId) externalviewreturns (stringmemory);
/**
* @dev Returns the profile ID according to a given handle.
*
* @param handle The handle to query.
*
* @return uint256 Profile ID the passed handle points to.
*/functiongetProfileIdByHandle(stringcalldata handle) externalviewreturns (uint256);
/**
* @dev Returns the profile struct of the given profile ID.
*
* @param profileId The profile ID to query.
*
* @return ProfileStruct The profile struct of the given profile ID.
*/functiongetProfile(uint256 profileId
) externalviewreturns (OspDataTypes.ProfileStruct memory);
/**
* @dev Returns the profile id according to a given address. if not found returns 0.
*
* @param addr The address to query.
*
* @return uint256 Profile ID associated with the address
*/functiongetProfileIdByAddress(address addr) externalviewreturns (uint256);
functionnonces(address singer) externalviewreturns (uint256);
}
Contract Source Code
File 77 of 124: IReferenceCondition.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;/**
* @title IReferenceCondition
* @author Osp Protocol
*
* @dev This is the standard interface for all Osp-compatible ReferenceConditions.
*/interfaceIReferenceCondition{
functioninitializeReferenceCondition(uint256 profileId,
uint256 contendId,
uint256 communityId,
bytescalldata data
) external;
functionprocessReactionReference(uint256 profileId,
uint256 communityId,
uint256 referencedProfileId,
uint256 referencedContentId,
bytescalldata data
) externalpayable;
}
Contract Source Code
File 78 of 124: IRelationLogic.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;import'../../../libraries/OspDataTypes.sol';
/**
* @title IReactionLogic
* @author OpenSocial Protocol
*
* @dev This is the interface for the ReactionLogic contract.
*/interfaceIRelationLogic{
/**
* @dev Follow a profile, executing the profile's follow condition logic (if any) and minting followSBTs to the caller.
*
* @return uint256 An integer representing the minted follow SBTs token ID.
*/functionfollow(OspDataTypes.FollowData calldata vars) externalpayablereturns (uint256);
/**
* @dev Follow a profile, executing the profile's follow condition logic (if any) and minting followSBTs to the caller.
* NOTE: Both the `profileIds` and `datas` arrays must be of the same length, regardless if the profiles do not have a follow condition set.
*
* @return uint256 An integer representing the minted follow SBTs token ID.
*/functionbatchFollow(
OspDataTypes.BatchFollowData calldata vars
) externalpayablereturns (uint256[] memory);
/**
* @dev Join a community, executing the community's join condition logic (if any) and minting joinNFTs to the caller.
*
* @return uint256 An integer representing the minted join NFTs token ID.
*/functionjoin(OspDataTypes.JoinData calldata vars) externalpayablereturns (uint256);
/**
* @dev Join a community, executing the community's join condition logic (if any) and minting joinNFTs to the caller.
* NOTE: Both the `communityIds` and `datas` arrays must be of the same length, regardless if the communities do not have a join condition set.
*
* @return uint256 An integer representing the minted join NFTs token ID.
*/functionbatchJoin(
OspDataTypes.BatchJoinData calldata vars
) externalpayablereturns (uint256[] memory);
/**
* @dev Returns the URI for a followSBT token.
*
* @param profileId The token ID of the profile associated with the follow SBT.
* @param tokenId The followSBTId being transferred's token ID.
*/functiongetFollowSBTURI(uint256 profileId,
uint256 tokenId
) externalviewreturns (stringmemory);
/**
* @dev Returns addr is follower for a gave profile.
*
* @param profileId The profileID to query.
* @param addr The address of the follower.
*/functionisFollow(uint256 profileId, address addr) externalviewreturns (bool);
/**
* @dev Returns addr is member for a gave community.
*
* @param communityId The communityID to query.
* @param addr The address of the member.
*/functionisJoin(uint256 communityId, address addr) externalviewreturns (bool);
/**
* @dev Returns `true` if the account has the specified role in the community.
*
* @param communityId The community ID to check the role for.
* @param role The role to check for.
* @param account The account to check the role for.
*/functionhasCommunityRole(uint256 communityId,
uint256 role,
address account
) externalviewreturns (bool);
/**
* @dev Returns the role of the account in the community.
*
* @param communityId The community ID to get the role.
* @param account The account to get role for.
*/functiongetCommunityRole(uint256 communityId, address account) externalviewreturns (uint256);
/**
* @dev Returns the level of the account in the community.
*
* @param communityId The community ID to get the level for.
* @param account The account to get level for.
*/functiongetCommunityMemberLevel(uint256 communityId,
address account
) externalviewreturns (uint256);
/**
* @dev Returns the block status of the account in the community.
*
* @param communityId The community ID to get the block status for.
* @param account The account to get block status for.
*/functionisCommunityBlock(uint256 communityId, address account) externalviewreturns (bool);
/**
* @dev Returns the URI for a joinNFT token.
*
* @param communityId The communityId associated with the join NFT.
* @param tokenId The joinNFTId being transferred's token ID.
*/functiongetJoinNFTURI(uint256 communityId,
uint256 tokenId
) externalviewreturns (stringmemory);
/**
* @dev emit FollowSBTTransaction event to facilitate the monitoring of events.
*
* @param profileId The token ID of the profile associated with the follow SBT being transferred.
* @param followSBTId The followSBTId being transferred's token ID.
* @param from The address the collectNFT is being transferred from.
* @param to The address the collectNFT is being transferred to.
*/functionemitFollowSBTTransferEvent(uint256 profileId,
uint256 followSBTId,
addressfrom,
address to
) external;
/**
* @dev emit JoinNFTTransaction event to facilitate the monitoring of events.
*
* @param communityId The communityId associated with the join NFT being transferred.
* @param joinNFTId The joinNFTId being transferred's token ID.
* @param from The address the joinNFT is being transferred from.
* @param to The address the joinNFT is being transferred to.
*/functionemitJoinNFTTransferEvent(uint256 communityId,
uint256 joinNFTId,
addressfrom,
address to
) external;
functionemitJoinNFTRoleChangedEvent(uint256 communityId,
address sender,
address account,
uint256 role
) external;
functionemitJoinNFTAccountBlockedEvent(uint256 communityId,
address sender,
address account,
bool isBlock
) external;
functionemitJoinNFTAccountLevelChangedEvent(uint256 communityId,
address sender,
uint256 tokenId,
address account,
uint256 level
) external;
}
Contract Source Code
File 79 of 124: IRoleActivityCond.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;import {IActivityCondition} from'contracts/interfaces/IActivityCondition.sol';
/**
* @title IRoleActivityCond
* @dev Have a community role to post
*/interfaceIRoleActivityCondisIActivityCondition{
/**
* @dev Returns the role limit for a given community.
* @param communityId The ID of the community.
* @return roleLimit The role limit for the community.
*/functiongetRoleLimit(uint256 communityId) externalviewreturns (uint256 roleLimit);
}
Contract Source Code
File 80 of 124: IRoleViewPrivacyCond.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;import {IViewPrivacyCondition} from'contracts/interfaces/IViewPrivacyCondition.sol';
/**
* @title IRoleViewPrivacyCond
* @dev Have a community role to view privacy
*/interfaceIRoleViewPrivacyCondisIViewPrivacyCondition{
/**
* @dev Struct to store role limit data.
*/structRoleLimitData {
uint256 roleLimit;
}
/**
* @dev Returns the role limit for a given community.
* @param communityId The ID of the community.
* @return roleLimit The role limit for the community.
*/functiongetRoleLimit(uint256 communityId) externalviewreturns (uint256 roleLimit);
}
Contract Source Code
File 81 of 124: IRouter.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;interfaceIRouter{
/**
* @dev An interface to describe a plug-in.
*
* @param functionSelector 4-byte function selector.
* @param functionSignature Function representation as a string. E.g. "transfer(address,address,uint256)"
* @param routerAddress Address of the contract containing the function.
*/structRouter {
bytes4 functionSelector;
address routerAddress;
string functionSignature;
}
/// @dev Emitted when a functionality is added, or plugged-in.eventRouterAdded(bytes4indexed functionSelector, addressindexed routerAddress);
/// @dev Emitted when a functionality is updated or overridden.eventRouterUpdated(bytes4indexed functionSelector,
addressindexed oldRouterAddress,
addressindexed newRouterAddress
);
/// @dev Emitted when a function selector is mapped to a particular plug-in smart contract, during construction of Map.eventRouterSet(bytes4indexed functionSelector,
stringindexed functionSignature,
addressindexed routerAddress
);
/// @dev Emitted when a functionality is removed.eventRouterRemoved(bytes4indexed functionSelector, addressindexed routerAddress);
/// @dev Add a new router to the contract.functionaddRouter(Router memory router) external;
/// @dev Update / override an existing router.functionupdateRouter(Router memory router) external;
/// @dev Remove an existing router from the contract.functionremoveRouter(bytes4 selector, stringcalldata functionSignature) external;
/// @dev Returns the plug-in contract for a given function.functiongetRouterForFunction(bytes4 functionSelector) externalviewreturns (address);
/// @dev Returns all functions that are mapped to the given plug-in contract.functiongetAllFunctionsOfRouter(address routerAddress) externalviewreturns (bytes4[] memory);
/// @dev Returns all plug-ins known by Map.functiongetAllRouters() externalviewreturns (Router[] memory);
}
Contract Source Code
File 82 of 124: IViewPrivacyCondition.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;/**
* @title IViewPrivacyCondition
* @author OpenSocial Protocol
*
* @dev This interface is used to define who can view the privacy content.
*/interfaceIViewPrivacyCondition{
/**
* @dev Initializes the view privacy condition for a community.
*
* @param communityId The ID of the community.
* @param data The data to initialize the view privacy condition.
*/functioninitializeCommunityViewPrivacyCondition(uint256 communityId,
bytescalldata data
) external;
/**
* @dev Checks if a profile can view the privacy content.
*
* @param communityId The ID of the community.
* @param profileOwner The owner of the profile.
* @param profileId The ID of the profile.
*
* @return A boolean indicating if the profile can view the privacy content.
*/functionisViewPrivacyAllowed(uint256 communityId,
address profileOwner,
uint256 profileId
) externalviewreturns (bool);
}
Contract Source Code
File 83 of 124: Initializable.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)pragmasolidity ^0.8.20;/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/abstractcontractInitializable{
/**
* @dev Storage of the initializable contract.
*
* It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions
* when using with upgradeable contracts.
*
* @custom:storage-location erc7201:openzeppelin.storage.Initializable
*/structInitializableStorage {
/**
* @dev Indicates that the contract has been initialized.
*/uint64 _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/bool _initializing;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff))bytes32privateconstant INITIALIZABLE_STORAGE =0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;
/**
* @dev The contract is already initialized.
*/errorInvalidInitialization();
/**
* @dev The contract is not initializing.
*/errorNotInitializing();
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/eventInitialized(uint64 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any
* number of times. This behavior in the constructor can be useful during testing and is not expected to be used in
* production.
*
* Emits an {Initialized} event.
*/modifierinitializer() {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
// Cache values to avoid duplicated sloadsbool isTopLevelCall =!$._initializing;
uint64 initialized = $._initialized;
// Allowed calls:// - initialSetup: the contract is not in the initializing state and no previous version was// initialized// - construction: the contract is initialized at version 1 (no reininitialization) and the// current contract is just being deployedbool initialSetup = initialized ==0&& isTopLevelCall;
bool construction = initialized ==1&&address(this).code.length==0;
if (!initialSetup &&!construction) {
revert InvalidInitialization();
}
$._initialized =1;
if (isTopLevelCall) {
$._initializing =true;
}
_;
if (isTopLevelCall) {
$._initializing =false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/modifierreinitializer(uint64 version) {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
if ($._initializing || $._initialized >= version) {
revert InvalidInitialization();
}
$._initialized = version;
$._initializing =true;
_;
$._initializing =false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/modifieronlyInitializing() {
_checkInitializing();
_;
}
/**
* @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.
*/function_checkInitializing() internalviewvirtual{
if (!_isInitializing()) {
revert NotInitializing();
}
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/function_disableInitializers() internalvirtual{
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
if ($._initializing) {
revert InvalidInitialization();
}
if ($._initialized !=type(uint64).max) {
$._initialized =type(uint64).max;
emit Initialized(type(uint64).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/function_getInitializedVersion() internalviewreturns (uint64) {
return _getInitializableStorage()._initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/function_isInitializing() internalviewreturns (bool) {
return _getInitializableStorage()._initializing;
}
/**
* @dev Returns a pointer to the storage namespace.
*/// solhint-disable-next-line var-name-mixedcasefunction_getInitializableStorage() privatepurereturns (InitializableStorage storage $) {
assembly {
$.slot:= INITIALIZABLE_STORAGE
}
}
}
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)pragmasolidity ^0.8.20;/**
* @dev Standard math utilities missing in the Solidity language.
*/libraryMath{
/**
* @dev Muldiv operation overflow.
*/errorMathOverflowedMulDiv();
enumRounding {
Floor, // Toward negative infinity
Ceil, // Toward positive infinity
Trunc, // Toward zero
Expand // Away from zero
}
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*/functiontryAdd(uint256 a, uint256 b) internalpurereturns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an overflow flag.
*/functiontrySub(uint256 a, uint256 b) internalpurereturns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*/functiontryMul(uint256 a, uint256 b) internalpurereturns (bool, uint256) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the// benefit is lost if 'b' is also tested.// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522if (a ==0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*/functiontryDiv(uint256 a, uint256 b) internalpurereturns (bool, uint256) {
unchecked {
if (b ==0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*/functiontryMod(uint256 a, uint256 b) internalpurereturns (bool, uint256) {
unchecked {
if (b ==0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Returns the largest of two numbers.
*/functionmax(uint256 a, uint256 b) internalpurereturns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/functionmin(uint256 a, uint256 b) internalpurereturns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/functionaverage(uint256 a, uint256 b) internalpurereturns (uint256) {
// (a + b) / 2 can overflow.return (a & b) + (a ^ b) /2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds towards infinity instead
* of rounding towards zero.
*/functionceilDiv(uint256 a, uint256 b) internalpurereturns (uint256) {
if (b ==0) {
// Guarantee the same behavior as in a regular Solidity division.return a / b;
}
// (a + b - 1) / b can overflow on addition, so we distribute.return a ==0 ? 0 : (a -1) / b +1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
* denominator == 0.
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
* Uniswap Labs also under MIT license.
*/functionmulDiv(uint256 x, uint256 y, uint256 denominator) internalpurereturns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256// variables such that product = prod1 * 2^256 + prod0.uint256 prod0 = x * y; // Least significant 256 bits of the productuint256 prod1; // Most significant 256 bits of the productassembly {
let mm :=mulmod(x, y, not(0))
prod1 :=sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.if (prod1 ==0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.// The surrounding unchecked block does not change this fact.// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.if (denominator <= prod1) {
revert MathOverflowedMulDiv();
}
///////////////////////////////////////////////// 512 by 256 division.///////////////////////////////////////////////// Make division exact by subtracting the remainder from [prod1 prod0].uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder :=mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 :=sub(prod1, gt(remainder, prod0))
prod0 :=sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator.// Always >= 1. See https://cs.stackexchange.com/q/138556/92363.uint256 twos = denominator & (0- denominator);
assembly {
// Divide denominator by twos.
denominator :=div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 :=div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos :=add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for// four bits. That is, denominator * inv = 1 mod 2^4.uint256 inverse = (3* denominator) ^2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also// works in modular arithmetic, doubling the correct bits in each step.
inverse *=2- denominator * inverse; // inverse mod 2^8
inverse *=2- denominator * inverse; // inverse mod 2^16
inverse *=2- denominator * inverse; // inverse mod 2^32
inverse *=2- denominator * inverse; // inverse mod 2^64
inverse *=2- denominator * inverse; // inverse mod 2^128
inverse *=2- denominator * inverse; // inverse mod 2^256// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/functionmulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internalpurereturns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (unsignedRoundsUp(rounding) &&mulmod(x, y, denominator) >0) {
result +=1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
* towards zero.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/functionsqrt(uint256 a) internalpurereturns (uint256) {
if (a ==0) {
return0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.//// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.//// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`//// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.uint256 result =1<< (log2(a) >>1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision// into the expected uint128 result.unchecked {
result = (result + a / result) >>1;
result = (result + a / result) >>1;
result = (result + a / result) >>1;
result = (result + a / result) >>1;
result = (result + a / result) >>1;
result = (result + a / result) >>1;
result = (result + a / result) >>1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/functionsqrt(uint256 a, Rounding rounding) internalpurereturns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/functionlog2(uint256 value) internalpurereturns (uint256) {
uint256 result =0;
unchecked {
if (value >>128>0) {
value >>=128;
result +=128;
}
if (value >>64>0) {
value >>=64;
result +=64;
}
if (value >>32>0) {
value >>=32;
result +=32;
}
if (value >>16>0) {
value >>=16;
result +=16;
}
if (value >>8>0) {
value >>=8;
result +=8;
}
if (value >>4>0) {
value >>=4;
result +=4;
}
if (value >>2>0) {
value >>=2;
result +=2;
}
if (value >>1>0) {
result +=1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/functionlog2(uint256 value, Rounding rounding) internalpurereturns (uint256) {
unchecked {
uint256 result =log2(value);
return result + (unsignedRoundsUp(rounding) &&1<< result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/functionlog10(uint256 value) internalpurereturns (uint256) {
uint256 result =0;
unchecked {
if (value >=10**64) {
value /=10**64;
result +=64;
}
if (value >=10**32) {
value /=10**32;
result +=32;
}
if (value >=10**16) {
value /=10**16;
result +=16;
}
if (value >=10**8) {
value /=10**8;
result +=8;
}
if (value >=10**4) {
value /=10**4;
result +=4;
}
if (value >=10**2) {
value /=10**2;
result +=2;
}
if (value >=10**1) {
result +=1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/functionlog10(uint256 value, Rounding rounding) internalpurereturns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (unsignedRoundsUp(rounding) &&10** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256 of a positive value rounded towards zero.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/functionlog256(uint256 value) internalpurereturns (uint256) {
uint256 result =0;
unchecked {
if (value >>128>0) {
value >>=128;
result +=16;
}
if (value >>64>0) {
value >>=64;
result +=8;
}
if (value >>32>0) {
value >>=32;
result +=4;
}
if (value >>16>0) {
value >>=16;
result +=2;
}
if (value >>8>0) {
result +=1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/functionlog256(uint256 value, Rounding rounding) internalpurereturns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (unsignedRoundsUp(rounding) &&1<< (result <<3) < value ? 1 : 0);
}
}
/**
* @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
*/functionunsignedRoundsUp(Rounding rounding) internalpurereturns (bool) {
returnuint8(rounding) %2==1;
}
}
Contract Source Code
File 89 of 124: MessageHashUtils.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MessageHashUtils.sol)pragmasolidity ^0.8.20;import {Strings} from"../Strings.sol";
/**
* @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing.
*
* The library provides methods for generating a hash of a message that conforms to the
* https://eips.ethereum.org/EIPS/eip-191[EIP 191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712]
* specifications.
*/libraryMessageHashUtils{
/**
* @dev Returns the keccak256 digest of an EIP-191 signed data with version
* `0x45` (`personal_sign` messages).
*
* The digest is calculated by prefixing a bytes32 `messageHash` with
* `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the
* hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method.
*
* NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with
* keccak256, although any bytes32 value can be safely used because the final digest will
* be re-hashed.
*
* See {ECDSA-recover}.
*/functiontoEthSignedMessageHash(bytes32 messageHash) internalpurereturns (bytes32 digest) {
/// @solidity memory-safe-assemblyassembly {
mstore(0x00, "\x19Ethereum Signed Message:\n32") // 32 is the bytes-length of messageHashmstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix
digest :=keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20)
}
}
/**
* @dev Returns the keccak256 digest of an EIP-191 signed data with version
* `0x45` (`personal_sign` messages).
*
* The digest is calculated by prefixing an arbitrary `message` with
* `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the
* hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method.
*
* See {ECDSA-recover}.
*/functiontoEthSignedMessageHash(bytesmemory message) internalpurereturns (bytes32) {
returnkeccak256(bytes.concat("\x19Ethereum Signed Message:\n", bytes(Strings.toString(message.length)), message));
}
/**
* @dev Returns the keccak256 digest of an EIP-191 signed data with version
* `0x00` (data with intended validator).
*
* The digest is calculated by prefixing an arbitrary `data` with `"\x19\x00"` and the intended
* `validator` address. Then hashing the result.
*
* See {ECDSA-recover}.
*/functiontoDataWithIntendedValidatorHash(address validator, bytesmemory data) internalpurereturns (bytes32) {
returnkeccak256(abi.encodePacked(hex"19_00", validator, data));
}
/**
* @dev Returns the keccak256 digest of an EIP-712 typed data (EIP-191 version `0x01`).
*
* The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with
* `\x19\x01` and hashing the result. It corresponds to the hash signed by the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712.
*
* See {ECDSA-recover}.
*/functiontoTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internalpurereturns (bytes32 digest) {
/// @solidity memory-safe-assemblyassembly {
let ptr :=mload(0x40)
mstore(ptr, hex"19_01")
mstore(add(ptr, 0x02), domainSeparator)
mstore(add(ptr, 0x22), structHash)
digest :=keccak256(ptr, 0x42)
}
}
}
Contract Source Code
File 90 of 124: Multicall.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/Multicall.sol)pragmasolidity ^0.8.20;import {Address} from"./Address.sol";
/**
* @dev Provides a function to batch together multiple calls in a single external call.
*/abstractcontractMulticall{
/**
* @dev Receives and executes a batch of function calls on this contract.
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/functionmulticall(bytes[] calldata data) externalvirtualreturns (bytes[] memory results) {
results =newbytes[](data.length);
for (uint256 i =0; i < data.length; i++) {
results[i] = Address.functionDelegateCall(address(this), data[i]);
}
return results;
}
}
Contract Source Code
File 91 of 124: NativeFeeJoinCond.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;import {CondErrors} from'../libraries/CondErrors.sol';
import {JoinConditionBase} from'../../base/JoinConditionBase.sol';
import {Payment} from'../../../libraries/Payment.sol';
/**
* @title CommunityData
* @param amount The amount of native tokens to charge for joining
* @param recipient The address to send the native tokens to
*/structCommunityData {
uint256 amount;
address recipient;
}
/**
* @title NativeFeeJoinCond
* @author OpenSocial
* @dev The condition allows users to join a community by paying a fee in native tokens.
*/contractNativeFeeJoinCondisJoinConditionBase{
mapping(uint256=> CommunityData) internal _dataByCommunity;
constructor(address osp) JoinConditionBase(osp) {}
/**
* @dev Initializes the condition data for a given community.
*/function_initializeCommunityJoinCondition(uint256 communityId,
bytescalldata data
) internaloverrideonlyOsp{
(uint256 amount, address recipient) =abi.decode(data, (uint256, address));
if (recipient ==address(0) || amount ==0) revert CondErrors.InitParamsInvalid();
_dataByCommunity[communityId].amount = amount;
_dataByCommunity[communityId].recipient = recipient;
}
/**
* @dev process join,transfer native token to recipient.
*/function_processJoin(address follower,
uint256 communityId,
bytescalldata data
) internaloverrideonlyOsp{
uint256 value =msg.value;
if (value != _dataByCommunity[communityId].amount)
revert CondErrors.ConditionDataMismatch();
Payment.payNative(_dataByCommunity[communityId].recipient, value);
(follower, data); //unused
}
/**
* @dev Returns the community data for a given community, or an empty struct if that community was not initialized
* with this condition.
*/functiongetCommunityData(uint256 communityId) externalviewreturns (CommunityData memory) {
return _dataByCommunity[communityId];
}
}
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;import'./IGovernanceLogic.sol';
import'./IProfileLogic.sol';
import'./IContentLogic.sol';
import'./IRelationLogic.sol';
import'./ICommunityLogic.sol';
import'../../../libraries/OspErrors.sol';
import'../../../libraries/OspEvents.sol';
/**
* @title OspClient
* @author OpenSocial Protocol
* @dev This is the interface for the OspClient contract,
* @dev This contract is used to generate the OpenSocial abi file.
*/interfaceOspClientisIGovernanceLogic,
IProfileLogic,
IContentLogic,
IRelationLogic,
ICommunityLogic{
}
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;/**
* @title OspDataTypes
* @author OpenSocial Protocol
*
* @dev The OspDataTypes library contains data types used throughout the OpenSocial Protocol.
*/libraryOspDataTypes{
bytes32internalconstant EIP712_DOMAIN_TYPEHASH =keccak256(
'EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'
);
bytes32internalconstant CREATE_ACTIVITY_WITH_SIG_TYPEHASH =keccak256(
'CreateActivityWithSig(uint256 profileId,uint256 communityId,string contentURI,bytes extensionInitCode,bytes referenceConditionInitCode,bytes ctx,uint256 nonce,uint256 deadline)'
);
bytes32internalconstant 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)'
);
bytes32internalconstant 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.
*/enumProtocolState {
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
*/structEIP712Signature {
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.
*/structProfileStruct {
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.
* @param activityCondition The address of the current activity condition in use by this community, can be empty.
*/structCommunityStruct {
string handle;
address joinCondition;
address joinNFT;
address activityCondition;
address viewPrivacyCondition;
}
structContentStruct {
uint256 communityId;
uint256 referencedProfileId;
uint256 referencedContentId;
string contentURI;
address extension;
address referenceCondition;
}
structPluginStruct {
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.
*/structCreateProfileData {
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.
*/structCreateActivityData {
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.
*/structCreateCommentData {
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.
*/structCreateMegaphoneData {
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.
*/structCreateOpenReactionData {
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.
*/structCreateCommunityData {
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.
*/structFollowData {
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.
*/structBatchFollowData {
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.
*/structJoinData {
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.
*/structBatchJoinData {
uint256[] communityIds;
bytes[] datas;
uint256[] values;
bytes ctx;
}
structRoyaltyInfo {
uint128 royaltyFraction;
uint128 ospTreasureFraction;
}
}
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;import {OspDataTypes} from'./OspDataTypes.sol';
libraryOspEvents{
eventOSPInitialized(string name,
string symbol,
address followSBTImpl,
address joinNFTImpl,
address communityNFT,
address communityAccountProxy,
uint256 timestamp
);
/**
* @dev Emitted when the osp state is set.
*
* @param caller The caller who set the state.
* @param prevState The previous protocol state, an enum of either `Paused`, `PublishingPaused` or `Unpaused`.
* @param newState The newly set state, an enum of either `Paused`, `PublishingPaused` or `Unpaused`.
* @param timestamp The current block timestamp.
*/eventStateSet(addressindexed caller,
OspDataTypes.ProtocolState indexed prevState,
OspDataTypes.ProtocolState indexed newState,
uint256 timestamp
);
eventBaseURISet(string communityNFTBaseURI, uint256 timestamp);
/**
* @dev Emitted when a app is added to or removed from the whitelist.
*
* @param app The address of the app.
* @param whitelisted Whether or not the reaction is being added to the whitelist.
* @param timestamp The current block timestamp.
*/eventAppWhitelisted(addressindexed app, boolindexed whitelisted, uint256 timestamp);
eventTokenWhitelisted(addressindexed token, boolindexed whitelisted, uint256 timestamp);
/**
* @dev Emitted when add or remove a reserve community handle.
*
* @param handleHash The hash of the handle to add or remove.
* @param handle The handle to add or remove.
* @param isReserved Whether or not the handle is being added to the reserve list.
* @param timestamp The current block timestamp.
*/eventCommunityHandleReserve(bytes32indexed handleHash,
boolindexed isReserved,
string handle,
uint256 timestamp
);
/**
* @dev Emitted when a profile is created.
*
* @param profileId The newly created profile's token ID.
* @param to The address receiving the profile with the given profile ID.
* @param handle The handle set for the profile.
* @param followCondition The profile's newly set follow condition. This CAN be the zero address.
* @param timestamp The current block timestamp.
*/eventProfileCreated(uint256indexed profileId,
addressindexed to,
string handle,
address followCondition,
uint256 inviter,
bytes ctx,
uint256 timestamp
);
/**
* @dev Emitted when a profile's follow condition is set.
*
* @param profileId The profile's token ID.
* @param followCondition The profile's newly set follow condition. This CAN be the zero address.
* @param timestamp The current block timestamp.
*/eventFollowConditionSet(uint256indexed profileId, address followCondition, uint256 timestamp);
/**
* @dev Emitted when a FollowSBT clone is deployed using a lazy deployment pattern.
*
* @param profileId The token ID of the profile to which this FollowSBT is associated.
* @param followSBT The address of the newly deployed FollowSBT clone.
* @param timestamp The current block timestamp.
*/eventFollowSBTDeployed(uint256indexed profileId,
addressindexed followSBT,
uint256 timestamp
);
/**
* @dev Emitted when a profile is updated.
*
* @param follower The address updating the profile.
* @param followerProfileId The token ID of the profile updating the profile.
* @param profileId The token ID of the profile being updated.
* @param followConditionData The data passed to the follow condition.
* @param tokenId The TokenNFT ID.
* @param timestamp The current block timestamp.
*/eventFollowed(addressindexed follower,
uint256indexed followerProfileId,
uint256 profileId,
bytes followConditionData,
uint256 tokenId,
bytes ctx,
uint256 timestamp
);
/**
* @dev Emitted upon a successful follow action.
*/eventBatchFollowed(addressindexed follower,
uint256 followerProfileId,
uint256[] profileIds,
bytes[] followConditionDatas,
uint256[] tokenIds,
bytes ctx,
uint256 timestamp
);
/**
* @dev Emitted via callback when a FollowSBT is transferred.
*
* @param profileId The token ID of the profile associated with the FollowSBT being transferred.
* @param followSBTId The FollowSBT being transferred's token ID.
* @param from The address the FollowSBT is being transferred from.
* @param to The address the FollowSBT is being transferred to.
* @param timestamp The current block timestamp.
*/eventFollowSBTTransferred(uint256indexed profileId,
uint256indexed followSBTId,
addressfrom,
address to,
uint256 timestamp
);
/**
* @dev Emitted via callback when a communityNFT is transferred.
*
* @param communityId The token ID of the community associated with the communityNFT being transferred.
* @param from The address the communityNFT is being transferred from.
* @param to The address the communityNFT is being transferred to.
* @param timestamp The current block timestamp.
*/eventCommunityNFTTransferred(uint256indexed communityId,
addressfrom,
address to,
uint256 timestamp
);
/**
* @dev Emitted via callback when a JoinNFT is transferred.
*
* @param joinNFTId The token ID of the profile associated with the JoinNFT being transferred.
* @param from The address the JoinNFT is being transferred from.
* @param to The address the JoinNFT is being transferred to.
* @param timestamp The current block timestamp.
*/eventJoinNFTTransferred(uint256indexed communityId,
uint256indexed joinNFTId,
addressfrom,
address to,
uint256 timestamp
);
/**
* @dev Emitted when a newly deployed follow NFT is initialized.
*
* @param profileId The token ID of the profile connected to this follow NFT.
* @param timestamp The current block timestamp.
*/eventFollowSBTInitialized(uint256indexed profileId, uint256 timestamp);
/**
* @dev Emitted when a newly deployed join NFT is initialized.
*
* @param communityId The unique ID of the community mapped to this collect NFT.
* @param timestamp The current block timestamp.
*/eventJoinNFTInitialized(uint256indexed communityId, uint256 timestamp);
/**
* @dev Emitted when a JoinNFT clone is deployed using a lazy deployment pattern.
*
* @param communityId The unique ID of the community mapped to this join NFT.
* @param joinNFT The address of the newly deployed joinNFT clone.
* @param timestamp The current block timestamp.
*/eventJoinNFTDeployed(uint256indexed communityId, addressindexed joinNFT, uint256 timestamp);
/**
* @dev Emitted when a community is created.
*
* @param communityId The token ID of the community being created.
* @param to The address receiving the community with the given community ID.
* @param handle The handle set for the community.
* @param communityConditionAndData Conditions for creating the community.
* @param joinCondition The community's newly set join condition. This CAN be the zero address.
* @param joinNFT The community's newly set join NFT.
*/eventCommunityCreated(uint256indexed communityId,
addressindexed to,
string handle,
bytes communityConditionAndData,
address joinCondition,
address joinNFT,
string[] tags,
bytes ctx,
uint256 timestamp
);
/**
* @dev Emitted when communityTag is updated.
*
* @param communityId The token ID of the community being updated.
* @param tags The new tags for the community.
*/eventCommunityTagsUpdated(uint256indexed communityId,
addressindexed sender,
string[] tags,
uint256 timestamp
);
/**
* @dev Emitted when you join a community.
*
* @param joiner The address joining the community.
* @param joinerProfileId The token ID of the profile joining the community.
* @param communityId The token ID of the community being joined.
* @param joinConditionData The data passed to the join condition.
* @param ctx The context passed to the join condition.
*/eventJoined(addressindexed joiner,
uint256 joinerProfileId,
uint256 communityId,
bytes joinConditionData,
uint256 tokenId,
bytes ctx,
uint256 timestamp
);
/**
* @dev Emitted when a batch of communities are joined.
*/eventBatchJoined(addressindexed joiner,
uint256 joinerProfileId,
uint256[] communityIds,
bytes[] joinConditionDatas,
uint256[] tokenIds,
bytes ctx,
uint256 timestamp
);
/**
* @dev Emitted when a community's join condition is set.
*
* @param communityId The community's token ID.
* @param joinCondition The community's newly set join condition. This CAN be the zero address.
* @param timestamp The current block timestamp.
*/eventJoinConditionSet(uint256indexed communityId,
addressindexed sender,
address joinCondition,
uint256 timestamp
);
/**
* @dev Emitted when a community's activity condition is set.
*
* @param communityId The community's token ID.
* @param activityCondition The community's newly set activity condition. This can be the zero address.
* @param timestamp The current block timestamp.
*/eventActivityConditionSet(uint256indexed communityId,
addressindexed sender,
address activityCondition,
uint256 timestamp
);
/**
* @dev Emitted when a community's view privacy condition is set.
*
* @param communityId The community's token ID.
* @param viewPrivacyCondition The community's newly set view privacy condition. This can be the zero address.
* @param timestamp The current block timestamp.
*/eventViewPrivacyConditionSet(uint256indexed communityId,
addressindexed sender,
address viewPrivacyCondition,
uint256 timestamp
);
eventActivityCreated(uint256indexed profileId,
uint256indexed contentId,
uint256 communityId,
string contentURI,
address extension,
address referenceCondition,
bytes ctx,
uint256 timestamp
);
eventCommentCreated(uint256indexed profileId,
uint256indexed contentId,
uint256 communityId,
string contentURI,
uint256 referencedProfileId,
uint256 referencedContentId,
address referenceCondition,
bytes ctx,
uint256 timestamp
);
eventOpenReactionCreated(uint256indexed profileId,
uint256indexed referencedProfileId,
uint256indexed referencedContentId,
uint256 communityId,
address openReaction,
bytes openReactionData,
bytes ctx,
uint256 timestamp
);
eventMegaphoneCreated(uint256indexed megaphoneId,
uint256indexed referencedProfileId,
uint256indexed referencedContentId,
uint256 profileId,
string[] tags,
uint256 startTime,
uint256 duration,
address currency,
uint256 amount,
bytes ctx,
uint256 timestamp
);
eventERC6551AccountImplSet(address accountImpl, uint256 timestamp);
eventJoinNFTImplSet(address accountImpl, uint256 timestamp);
eventJoinNFTRoleChanged(uint256indexed communityId,
addressindexed sender,
addressindexed account,
uint256 role,
uint256 timestamp
);
eventJoinNFTAccountBlocked(uint256indexed communityId,
addressindexed sender,
addressindexed account,
bool isBlock,
uint256 timestamp
);
eventJoinNFTAccountLevelChanged(uint256indexed communityId,
uint256indexed tokenId,
addressindexed sender,
address account,
address communityJoinNFT,
uint256 level,
uint256 timestamp
);
eventCommunityExtensionWhitelistSet(uint256indexed communityId,
addressindexed extension,
boolindexed isWhitelist,
address sender,
uint256 timestamp
);
}
Contract Source Code
File 99 of 124: OspHelpers.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;import'./OspDataTypes.sol';
import'./OspErrors.sol';
/**
* @title OspHelpers
* @author OpenSocial Protocol
*
* @dev This is a library that only contains a single function that is used in the osp contract as well as in
* both the publishing logic and interaction logic libraries.
*/libraryOspHelpers{
/**
* @dev This helper function just returns the pointed content if the passed content is a mirror,
* otherwise it returns the passed publication.
*
* @param profileId The token ID of the profile that published the given publication.
* @param contentId The content ID of the given publication.
* @param _contentByIdByProfile A pointer to the storage mapping of publications by contentId by profile ID.
*
* @return tuple First, the pointed publication's publishing profile ID, second, the pointed publication's ID, and third, the
* pointed publication's collect . If the passed content is not a mirror, this returns the given publication.
*/functiongetPointedIfWithContentRoot(uint256 profileId,
uint256 contentId,
mapping(uint256 => mapping(uint256 => OspDataTypes.ContentStruct))
storage _contentByIdByProfile
) internalviewreturns (uint256, uint256) {
stringmemory contentURI = _contentByIdByProfile[profileId][contentId].contentURI;
if (bytes(contentURI).length==0) {
uint256 pointedTokenId = _contentByIdByProfile[profileId][contentId]
.referencedProfileId;
if (pointedTokenId ==0) revert OspErrors.ContentDoesNotExist();
uint256 pointedcontentId = _contentByIdByProfile[profileId][contentId]
.referencedContentId;
return (pointedTokenId, pointedcontentId);
} else {
return (profileId, contentId);
}
}
}
Contract Source Code
File 100 of 124: OspLogicBase.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;import {OspStorage} from'contracts/core/storage/OspStorage.sol';
import {OspMultiState} from'contracts/core/base/OspMultiState.sol';
import {EIP712Base} from'contracts/core/base/EIP712Base.sol';
import {OspErrors} from'contracts/libraries/OspErrors.sol';
import {OspEvents} from'contracts/libraries/OspEvents.sol';
import {OspDataTypes} from'contracts/libraries/OspDataTypes.sol';
import {IJoinCondition} from'contracts/interfaces/IJoinCondition.sol';
import {IOpenReaction} from'contracts/interfaces/IOpenReaction.sol';
import {IActivityExtension} from'contracts/interfaces/IActivityExtension.sol';
import {IReferenceCondition} from'contracts/interfaces/IReferenceCondition.sol';
import {ICommunityCondition} from'contracts/interfaces/ICommunityCondition.sol';
import {IFollowCondition} from'contracts/interfaces/IFollowCondition.sol';
import {IActivityCondition} from'contracts/interfaces/IActivityCondition.sol';
import {IViewPrivacyCondition} from'contracts/interfaces/IViewPrivacyCondition.sol';
import {ERC165Checker} from'@openzeppelin/contracts/utils/introspection/ERC165Checker.sol';
import {AccessControlUpgradeable} from'@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol';
/**
* @title OspLogicBase
* @author OpenSocial Protocol
* @dev The OspLogicBase contract includes methods for modifying contract state and some common methods that all Logic contracts must inherit.
*/contractOspLogicBaseisOspMultiState, OspStorage, EIP712Base{
/*///////////////////////////////////////////////////////////////
modifiers
//////////////////////////////////////////////////////////////*//*///////////////////////////////////////////////////////////////
Internal functions
//////////////////////////////////////////////////////////////*/function_checkFollowCondition(address followCondition) internalview{
if (
!_getGovernanceStorage()._appWhitelisted[followCondition] ||!ERC165Checker.supportsInterface(followCondition, type(IFollowCondition).interfaceId)
) revert OspErrors.AppNotWhitelisted();
}
function_checkCommunityCondition(address communityCondition) internalview{
if (
!_getGovernanceStorage()._appWhitelisted[communityCondition] ||!ERC165Checker.supportsInterface(
communityCondition,
type(ICommunityCondition).interfaceId
)
) revert OspErrors.AppNotWhitelisted();
}
function_checkJoinCondition(address joinCondition) internalview{
if (
!_getGovernanceStorage()._appWhitelisted[joinCondition] ||!ERC165Checker.supportsInterface(joinCondition, type(IJoinCondition).interfaceId)
) revert OspErrors.AppNotWhitelisted();
}
function_checkActivityCondition(address activityCondition) internalview{
if (
!_getGovernanceStorage()._appWhitelisted[activityCondition] ||!ERC165Checker.supportsInterface(
activityCondition,
type(IActivityCondition).interfaceId
)
) revert OspErrors.AppNotWhitelisted();
}
function_checkViewPrivacyCondition(address privacyCondition) internalview{
if (
!_getGovernanceStorage()._appWhitelisted[privacyCondition] ||!ERC165Checker.supportsInterface(
privacyCondition,
type(IViewPrivacyCondition).interfaceId
)
) revert OspErrors.AppNotWhitelisted();
}
function_checkActivityExtension(address extension) internalview{
if (
!_getGovernanceStorage()._appWhitelisted[extension] ||!ERC165Checker.supportsInterface(extension, type(IActivityExtension).interfaceId)
) revert OspErrors.AppNotWhitelisted();
}
function_checkOpenReaction(address openReaction) internalview{
if (
!_getGovernanceStorage()._appWhitelisted[openReaction] ||!ERC165Checker.supportsInterface(openReaction, type(IOpenReaction).interfaceId)
) revert OspErrors.AppNotWhitelisted();
}
function_checkReferenceCondition(address referenceCondition) internalview{
if (
!_getGovernanceStorage()._appWhitelisted[referenceCondition] ||!ERC165Checker.supportsInterface(
referenceCondition,
type(IReferenceCondition).interfaceId
)
) revert OspErrors.AppNotWhitelisted();
}
function_hashRole(bytes32 role, address account) internalviewreturns (bool) {
AccessControlUpgradeable.AccessControlStorage storage $;
assembly {
$.slot:=0x02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800
}
return $._roles[role].hasRole[account];
}
/**
* @dev This function reverts if the caller is not the owner of the profile.
*/function_validateIsProfileOwner(address addr, uint256 profileId) internalview{
if (addr != _ownerOf(profileId)) revert OspErrors.NotProfileOwner();
}
/**
* @dev This function reverts if the address is not has profile.
*/function_validateHasProfile(address addr) internalviewreturns (uint256) {
uint256 profileId = _getProfileStorage()._profileIdByAddress[addr];
if (profileId ==0) revert OspErrors.NotHasProfile();
return profileId;
}
/**
* @dev Returns the owner of the profile.
*/function_ownerOf(uint256 profileId) internalviewreturns (address) {
return _getProfileStorage()._profileById[profileId].owner;
}
function_calculateDomainSeparator() internalviewvirtualoverridereturns (bytes32) {
returnkeccak256(
abi.encode(
OspDataTypes.EIP712_DOMAIN_TYPEHASH,
keccak256(bytes(_getGovernanceStorage()._name)),
EIP712_REVISION_HASH,
block.chainid,
address(this)
)
);
}
}
Contract Source Code
File 101 of 124: OspMultiState.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;import'../../libraries/OspEvents.sol';
import'../../libraries/OspDataTypes.sol';
import'../../libraries/OspErrors.sol';
/**
* @title OspMultiState
*
* @dev This is an abstract contract that implements internal state setting and validation.
*
* whenNotPaused: Either publishingPaused or Unpaused.
* whenPublishingEnabled: When Unpaused only.
*/abstractcontractOspMultiState{
structProtocolStateStorage {
OspDataTypes.ProtocolState state;
}
bytes32internalconstant STATE_STORAGE_POSITION =keccak256('osp.state.storage');
modifierwhenNotPaused() {
_validateNotPaused();
_;
}
modifierwhenPublishingEnabled() {
_validatePublishingEnabled();
_;
}
functionprotocolStateStorage()
internalpurereturns (ProtocolStateStorage storage protocolState)
{
bytes32 position = STATE_STORAGE_POSITION;
assembly {
protocolState.slot:= position
}
}
/**
* @dev Returns the current protocol state.
*
* @return ProtocolState The Protocol state, an enum, where:
* 0: Unpaused
* 1: PublishingPaused
* 2: Paused
*/function_getState() internalviewreturns (OspDataTypes.ProtocolState) {
return protocolStateStorage().state;
}
function_setState(OspDataTypes.ProtocolState newState) internal{
OspDataTypes.ProtocolState prevState = protocolStateStorage().state;
protocolStateStorage().state = newState;
emit OspEvents.StateSet(msg.sender, prevState, newState, block.timestamp);
}
function_validatePublishingEnabled() internalview{
if (protocolStateStorage().state != OspDataTypes.ProtocolState.Unpaused) {
revert OspErrors.PublishingPaused();
}
}
function_validateNotPaused() internalview{
if (protocolStateStorage().state == OspDataTypes.ProtocolState.Paused)
revert OspErrors.Paused();
}
}
Contract Source Code
File 102 of 124: OspNFTBase.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;import {ERC721BurnableUpgradeable} from'@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721BurnableUpgradeable.sol';
import {ERC721EnumerableUpgradeable} from'@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721EnumerableUpgradeable.sol';
import {ERC721Upgradeable} from'@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol';
/**
* @title OspNFTBase
* @author OpenSocial Protocol
*
* @dev This is an abstract base contract to be inherited by other OpenSocial Protocol NFTs, it includes
* the ERC721EnumerableUpgradeable and ERC721BurnableUpgradeable.
*/abstractcontractOspNFTBaseisERC721EnumerableUpgradeable, ERC721BurnableUpgradeable{
function_initialize(stringmemory name, stringmemory symbol) internalinitializer{
__ERC721_init(name, symbol);
}
function_update(address to,
uint256 tokenId,
address auth
)
internaloverride(ERC721EnumerableUpgradeable, ERC721Upgradeable)
returns (address previousOwner)
{
previousOwner = ERC721EnumerableUpgradeable._update(to, tokenId, auth);
_afterTokenTransfer(previousOwner, to, tokenId);
}
function_afterTokenTransfer(addressfrom, address to, uint256 tokenId) internalvirtual{}
functionsupportsInterface(bytes4 interfaceId
) publicviewvirtualoverride(ERC721EnumerableUpgradeable, ERC721Upgradeable) returns (bool) {
return ERC721EnumerableUpgradeable.supportsInterface(interfaceId);
}
function_increaseBalance(address account,
uint128 amount
) internalvirtualoverride(ERC721EnumerableUpgradeable, ERC721Upgradeable) {
ERC721EnumerableUpgradeable._increaseBalance(account, amount);
}
}
Contract Source Code
File 103 of 124: OspRouterImmutable.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;import'./IRouter.sol';
import'@openzeppelin/contracts/utils/introspection/ERC165.sol';
import'@openzeppelin/contracts/utils/structs/EnumerableSet.sol';
import'@openzeppelin/contracts/proxy/Proxy.sol';
import'@openzeppelin/contracts/utils/Multicall.sol';
contractOspRouterImmutableisMulticall, ERC165, IRouter, Proxy{
usingEnumerableSetforEnumerableSet.Bytes32Set;
/*///////////////////////////////////////////////////////////////
struct and event definitions
//////////////////////////////////////////////////////////////*/structData {
address admin;
EnumerableSet.Bytes32Set allSelectors;
mapping(address=> EnumerableSet.Bytes32Set) selectorsForRouter;
mapping(bytes4=> Router) routerForSelector;
address pendingAdmin;
uint96 pendingAdminTimestamp;
}
/**
* @dev Emitted when the admin account has changed.
*/eventAdminChanged(address previousAdmin, address newAdmin);
eventChangeAdminStarted(address pendingAdmin, uint256 pendingAdminTimestamp);
eventPendingAdminRevoked(address pendingAdmin);
/*///////////////////////////////////////////////////////////////
Constructor + initializer logic
//////////////////////////////////////////////////////////////*/constructor(address admin_) {
_changeAdmin(admin_);
}
/*///////////////////////////////////////////////////////////////
routerStorage
//////////////////////////////////////////////////////////////*/bytes32internalconstant ROUTER_STORAGE_POSITION =keccak256('osp.router.storage');
functionrouterStorage() internalpurereturns (Data storage routerData) {
bytes32 position = ROUTER_STORAGE_POSITION;
assembly {
routerData.slot:= position
}
}
/*///////////////////////////////////////////////////////////////
ERC 165
//////////////////////////////////////////////////////////////*//**
* @dev See {IERC165-supportsInterface}.
*/functionsupportsInterface(bytes4 interfaceId) publicviewvirtualoverridereturns (bool) {
if (interfaceId ==type(IRouter).interfaceId||super.supportsInterface(interfaceId)) {
returntrue;
} else {
address implementation = _implementation();
return
implementation ==address(0)
? false
: IERC165(implementation).supportsInterface(interfaceId);
}
}
/*///////////////////////////////////////////////////////////////
Generic contract logic
//////////////////////////////////////////////////////////////*/modifieronlyAdmin() {
Data storage data = routerStorage();
require(msg.sender== data.admin, 'Router: Not authorized.');
_;
}
/*///////////////////////////////////////////////////////////////
External functions
//////////////////////////////////////////////////////////////*/functionchangeAdmin(address _newAdmin) publiconlyAdmin{
Data storage data = routerStorage();
data.pendingAdmin = _newAdmin;
data.pendingAdminTimestamp =uint96(block.timestamp);
emit ChangeAdminStarted(_newAdmin, block.timestamp);
}
functionrevokePendingAdmin() publiconlyAdmin{
Data storage data = routerStorage();
address pendingAdmin = data.pendingAdmin;
data.pendingAdmin =address(0);
data.pendingAdminTimestamp =0;
emit PendingAdminRevoked(pendingAdmin);
}
functionacceptAdminRole() public{
Data storage data = routerStorage();
require(
msg.sender== data.pendingAdmin &&block.timestamp> data.pendingAdminTimestamp +1days,
'Router: Admin role not available.'
);
_changeAdmin(data.pendingAdmin);
data.pendingAdmin =address(0);
data.pendingAdminTimestamp =0;
}
functiongetAdmin() publicviewreturns (address) {
Data storage data = routerStorage();
return data.admin;
}
functiongetPendingAdmin() publicviewreturns (address) {
Data storage data = routerStorage();
return data.pendingAdmin;
}
functiongetPendingAdminTimestamp() publicviewreturns (uint96) {
Data storage data = routerStorage();
return data.pendingAdminTimestamp;
}
/// @dev Add functionality to the contract.functionaddRouter(Router memory _router) publiconlyAdmin{
_addRouter(_router);
}
/// @dev Update or override existing functionality.functionupdateRouter(Router memory _router) publiconlyAdmin{
_updateRouter(_router);
}
/// @dev Remove existing functionality from the contract.functionremoveRouter(bytes4 selector, stringcalldata functionSignature) publiconlyAdmin{
_removeRouter(selector, functionSignature);
}
/*///////////////////////////////////////////////////////////////
View functions
//////////////////////////////////////////////////////////////*//// @dev View address of the plugged-in functionality contract for a given function signature.functiongetRouterForFunction(bytes4 _selector) publicviewreturns (address) {
return _getRouterForFunction(_selector);
}
/// @dev View all funtionality as list of function signatures.functiongetAllFunctionsOfRouter(address _routerAddress
) publicviewreturns (bytes4[] memory registered) {
Data storage data = routerStorage();
uint256 count = data.selectorsForRouter[_routerAddress].length();
registered =newbytes4[](count);
for (uint256 i; i < count; i +=1) {
registered[i] =bytes4(data.selectorsForRouter[_routerAddress].at(i));
}
}
/// @dev View all funtionality existing on the contract.functiongetAllRouters() publicviewreturns (Router[] memory registered) {
Data storage data = routerStorage();
EnumerableSet.Bytes32Set storage selectors = data.allSelectors;
uint256 count = selectors.length();
registered =new Router[](count);
for (uint256 i; i < count; i +=1) {
registered[i] = data.routerForSelector[bytes4(selectors.at(i))];
}
}
/*///////////////////////////////////////////////////////////////
Internal functions
//////////////////////////////////////////////////////////////*/function_implementation() internalviewvirtualoverridereturns (address) {
address router = _getRouterForFunction(msg.sig);
require(router !=address(0), 'Router: Not found.');
return router;
}
/// @dev View address of the plugged-in functionality contract for a given function signature.function_getRouterForFunction(bytes4 _selector) publicviewreturns (address) {
Data storage data = routerStorage();
return data.routerForSelector[_selector].routerAddress;
}
/// @dev Add functionality to the contract.function_addRouter(Router memory _router) internal{
Data storage data = routerStorage();
require(
data.allSelectors.add(bytes32(_router.functionSelector)),
'Router: router exists for function.'
);
require(
_router.functionSelector ==bytes4(keccak256(abi.encodePacked(_router.functionSignature))),
'Router: fn selector and signature mismatch.'
);
data.routerForSelector[_router.functionSelector] = _router;
data.selectorsForRouter[_router.routerAddress].add(bytes32(_router.functionSelector));
emit RouterAdded(_router.functionSelector, _router.routerAddress);
}
/// @dev Update or override existing functionality.function_updateRouter(Router memory _router) internal{
address currentRouter = getRouterForFunction(_router.functionSelector);
require(currentRouter !=address(0), 'Router: No router available for selector.');
require(
_router.functionSelector ==bytes4(keccak256(abi.encodePacked(_router.functionSignature))),
'Router: fn selector and signature mismatch.'
);
Data storage data = routerStorage();
data.allSelectors.add(bytes32(_router.functionSelector));
data.routerForSelector[_router.functionSelector] = _router;
data.selectorsForRouter[currentRouter].remove(bytes32(_router.functionSelector));
data.selectorsForRouter[_router.routerAddress].add(bytes32(_router.functionSelector));
emit RouterUpdated(_router.functionSelector, currentRouter, _router.routerAddress);
}
/// @dev Remove existing functionality from the contract.function_removeRouter(bytes4 _selector, stringcalldata _functionSignature) internal{
Data storage data = routerStorage();
address currentRouter = _getRouterForFunction(_selector);
require(currentRouter !=address(0), 'Router: No router available for selector.');
require(
_selector ==bytes4(keccak256(abi.encodePacked(_functionSignature))),
'Router: fn selector and signature mismatch.'
);
delete data.routerForSelector[_selector];
data.allSelectors.remove(_selector);
data.selectorsForRouter[currentRouter].remove(bytes32(_selector));
emit RouterRemoved(_selector, currentRouter);
}
function_changeAdmin(address admin_) internal{
Data storage data = routerStorage();
emit AdminChanged(data.admin, admin_);
data.admin = admin_;
}
}
Contract Source Code
File 104 of 124: OspSBTBase.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;import {OspNFTBase} from'./OspNFTBase.sol';
import {OspErrors} from'../../libraries/OspErrors.sol';
/**
* @title OspSBTBase
* @author OpenSocial Protocol
*
* @dev This is an abstract base contract to be inherited by other OpenSocial Protocol SBTs, it includes
* the ERC721EnumerableUpgradeable and ERC721BurnableUpgradeable.
* SBTs are not transferable, they can only be minted and burned.
*/abstractcontractOspSBTBaseisOspNFTBase{
function_afterTokenTransfer(addressfrom,
address to,
uint256/*tokenId*/) internalvirtualoverride{
if (from!=address(0) && to !=address(0)) {
revert OspErrors.SBTTransferNotAllowed();
}
if (from==address(0) && to !=address(0) && balanceOf(to) >1) {
revert OspErrors.SBTTokenAlreadyExists();
}
}
}
Contract Source Code
File 105 of 124: OspStorage.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;import'../../libraries/OspDataTypes.sol';
import {EnumerableSet} from'@openzeppelin/contracts/utils/structs/EnumerableSet.sol';
/**
* @title OspStorage
* @author OpenSocial Protocol
*
* @dev This abstract contract defines storage for the Osp protocol.
* Each condition' storage in a different slot.
* The order within the condition storage structure cannot be changed.
*/abstractcontractOspStorage{
/*///////////////////////////////////////////////////////////////
ProfileStorage
//////////////////////////////////////////////////////////////*/bytes32internalconstant PROFILE_STORAGE_POSITION =keccak256('osp.profile.storage');
structProfileStorage {
// Array with all token ids, used for enumerationuint256[] _allTokens;
// Mapping from token id to position in the allTokens arraymapping(uint256=>uint256) _allTokensIndex;
mapping(bytes32=>uint256) _profileIdByHandleHash;
mapping(uint256=> OspDataTypes.ProfileStruct) _profileById;
mapping(address=>uint256) _profileIdByAddress;
uint256 _profileCounter;
mapping(address=>uint256) _sigNonces;
}
function_getProfileStorage() internalpurereturns (ProfileStorage storage profileStorage) {
bytes32 position = PROFILE_STORAGE_POSITION;
assembly {
profileStorage.slot:= position
}
}
/*///////////////////////////////////////////////////////////////
ContentStorage
//////////////////////////////////////////////////////////////*/bytes32internalconstant PUBLICATION_STORAGE_POSITION =keccak256('osp.content.storage');
structContentStorage {
mapping(uint256=>mapping(uint256=> OspDataTypes.ContentStruct)) _contentByIdByProfile;
//tag 最多10个uint256 _megaphoneCount;
}
function_getContentStorage()
internalpurereturns (ContentStorage storage publicationStorage)
{
bytes32 position = PUBLICATION_STORAGE_POSITION;
assembly {
publicationStorage.slot:= position
}
}
/*///////////////////////////////////////////////////////////////
GovernanceStorage
//////////////////////////////////////////////////////////////*/bytes32internalconstant GOVERNANCE_STORAGE_POSITION =keccak256('osp.governance.storage');
structGovernanceStorage {
string _name;
string _symbol;
address _followSBTImpl;
address _joinNFTImpl;
address _communityNFT;
address _communityAccountProxy;
address _erc6551AccountImpl;
string _baseURI;
mapping(address=>bool) _appWhitelisted;
mapping(bytes32=>bool) _reserveCommunityHandleHash;
mapping(address=>bool) _tokenWhitelisted;
mapping(address=>bool) DEPRECATED_superCommunityCreatorWhitelisted;
address _treasure;
OspDataTypes.RoyaltyInfo _joinNFTRoyaltyInfo;
}
function_getGovernanceStorage()
internalpurereturns (GovernanceStorage storage governanceStorage)
{
bytes32 position = GOVERNANCE_STORAGE_POSITION;
assembly {
governanceStorage.slot:= position
}
}
/*///////////////////////////////////////////////////////////////
CommunityStorage
//////////////////////////////////////////////////////////////*/bytes32internalconstant COMMUNITY_STORAGE_POSITION =keccak256('osp.community.storage');
structCommunityStorage {
mapping(uint256=> OspDataTypes.CommunityStruct) _communityById;
mapping(bytes32=>uint256) _communityIdByHandleHash;
mapping(uint256=> EnumerableSet.AddressSet) _activityExtensionWhitelistByCommunity;
}
function_getCommunityStorage()
internalpurereturns (CommunityStorage storage communityStorage)
{
bytes32 position = COMMUNITY_STORAGE_POSITION;
assembly {
communityStorage.slot:= position
}
}
}
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (proxy/Proxy.sol)pragmasolidity ^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.
*/abstractcontractProxy{
/**
* @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) internalvirtual{
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.case0 {
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() internalviewvirtualreturns (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() internalvirtual{
_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() externalpayablevirtual{
_fallback();
}
}
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)pragmasolidity ^0.8.20;import {IERC20} from"../IERC20.sol";
import {IERC20Permit} from"../extensions/IERC20Permit.sol";
import {Address} from"../../../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.
*/librarySafeERC20{
usingAddressforaddress;
/**
* @dev An operation with an ERC20 token failed.
*/errorSafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/errorSafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @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.
*/functionsafeTransfer(IERC20 token, address to, uint256 value) internal{
_callOptionalReturn(token, abi.encodeCall(token.transfer, (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.
*/functionsafeTransferFrom(IERC20 token, addressfrom, address to, uint256 value) internal{
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, 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.
*/functionsafeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal{
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*/functionsafeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal{
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @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.
*/functionforceApprove(IERC20 token, address spender, uint256 value) internal{
bytesmemory approvalCall =abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @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, bytesmemory 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.bytesmemory returndata =address(token).functionCall(data);
if (returndata.length!=0&&!abi.decode(returndata, (bool))) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @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, bytesmemory data) privatereturns (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, bytesmemory returndata) =address(token).call(data);
return success && (returndata.length==0||abi.decode(returndata, (bool))) &&address(token).code.length>0;
}
}
Contract Source Code
File 116 of 124: SignatureChecker.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/SignatureChecker.sol)pragmasolidity ^0.8.20;import {ECDSA} from"./ECDSA.sol";
import {IERC1271} from"../../interfaces/IERC1271.sol";
/**
* @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA
* signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like
* Argent and Safe Wallet (previously Gnosis Safe).
*/librarySignatureChecker{
/**
* @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the
* signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`.
*
* NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus
* change through time. It could return true at block N and false at block N+1 (or the opposite).
*/functionisValidSignatureNow(address signer, bytes32 hash, bytesmemory signature) internalviewreturns (bool) {
(address recovered, ECDSA.RecoverError error, ) = ECDSA.tryRecover(hash, signature);
return
(error == ECDSA.RecoverError.NoError && recovered == signer) ||
isValidERC1271SignatureNow(signer, hash, signature);
}
/**
* @dev Checks if a signature is valid for a given signer and data hash. The signature is validated
* against the signer smart contract using ERC1271.
*
* NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus
* change through time. It could return true at block N and false at block N+1 (or the opposite).
*/functionisValidERC1271SignatureNow(address signer,
bytes32 hash,
bytesmemory signature
) internalviewreturns (bool) {
(bool success, bytesmemory result) = signer.staticcall(
abi.encodeCall(IERC1271.isValidSignature, (hash, signature))
);
return (success &&
result.length>=32&&abi.decode(result, (bytes32)) ==bytes32(IERC1271.isValidSignature.selector));
}
}
Contract Source Code
File 117 of 124: SignedMath.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol)pragmasolidity ^0.8.20;/**
* @dev Standard signed math utilities missing in the Solidity language.
*/librarySignedMath{
/**
* @dev Returns the largest of two signed numbers.
*/functionmax(int256 a, int256 b) internalpurereturns (int256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two signed numbers.
*/functionmin(int256 a, int256 b) internalpurereturns (int256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two signed numbers without overflow.
* The result is rounded towards zero.
*/functionaverage(int256 a, int256 b) internalpurereturns (int256) {
// Formula from the book "Hacker's Delight"int256 x = (a & b) + ((a ^ b) >>1);
return x + (int256(uint256(x) >>255) & (a ^ b));
}
/**
* @dev Returns the absolute unsigned value of a signed value.
*/functionabs(int256 n) internalpurereturns (uint256) {
unchecked {
// must be unchecked in order to support `n = type(int256).min`returnuint256(n >=0 ? n : -n);
}
}
}
Contract Source Code
File 118 of 124: SlotNFTCommunityCond.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;import {CondErrors} from'../libraries/CondErrors.sol';
import {IERC721} from'@openzeppelin/contracts/token/ERC721/IERC721.sol';
import {CommunityCondBase} from'../../base/CommunityCondBase.sol';
import {CondDataTypes} from'../libraries/CondDataTypes.sol';
/**
* @title SlotNFTCommunityCond
* @author OpenSocial Protocol
*
* @dev This contract specifies that holding slotNFT can create communities.
* Each slotNFT can only be used once.
*/contractSlotNFTCommunityCondisCommunityCondBase{
eventSlotNFTCondDataSet(addressindexed slot, uint256 minHandleLength, uint256 timestamp);
eventSlotNFTUsed(addressindexed to,
addressindexed slot,
uint256indexed tokenId,
string handle,
uint256 timestamp
);
constructor(address osp) CommunityCondBase(osp) {}
mapping(address=>mapping(uint256=>bool)) _slotNFTUsed;
mapping(address=> CondDataTypes.SlotNFTCondData) _slotNFTCondData;
/**
* @dev process create community,if the slotNFT is used, revert.
*/function_processCreateCommunity(address to,
stringcalldata handle,
bytescalldata data
) internaloverridenonPayable{
(address slot, uint256 tokenId) =abi.decode(data, (address, uint256));
_validateSlotNFT(to, slot, tokenId);
uint256 len =bytes(handle).length;
if (len < _slotNFTCondData[slot].minHandleLength) {
revert CondErrors.HandleLengthNotEnough();
}
_slotNFTUsed[slot][tokenId] =true;
emit SlotNFTUsed(to, slot, tokenId, handle, block.timestamp);
}
/**
* @dev Set slotNFT condition data.
* @param slot NFT contract address.
* @param whitelist Whether the slotNFT is whitelisted.
* @param minHandleLength Minimum handle length to create a community.
*/functionsetSlotNFTCondData(address slot,
bool whitelist,
uint256 minHandleLength
) externalonlyOperation{
if (slot ==address(0) || minHandleLength <=0) {
revert CondErrors.InitParamsInvalid();
}
_slotNFTCondData[slot] = CondDataTypes.SlotNFTCondData({
whitelist: whitelist,
minHandleLength: minHandleLength
});
emit SlotNFTCondDataSet(slot, minHandleLength, block.timestamp);
}
functiongetSlotNFTCondData(address slot
) externalviewreturns (CondDataTypes.SlotNFTCondData memory) {
return _slotNFTCondData[slot];
}
/**
* @dev Check if a slotNFT is usable.
* @param slot NFT contract address.
* @param addr Creator address.
* @param tokenId NFT token id.
*/functionisSlotNFTUsable(address slot,
address addr,
uint256 tokenId
) externalviewreturns (bool) {
return
_slotNFTCondData[slot].whitelist &&!_slotNFTUsed[slot][tokenId] &&
IERC721(slot).ownerOf(tokenId) == addr;
}
function_validateSlotNFT(address addr, address slot, uint256 tokenId) internalview{
if (!_slotNFTCondData[slot].whitelist) {
revert CondErrors.SlotNFTNotWhitelisted();
}
if (IERC721(slot).ownerOf(tokenId) != addr) {
revert CondErrors.NotSlotNFTOwner();
}
if (_slotNFTUsed[slot][tokenId]) {
revert CondErrors.SlotNFTAlreadyUsed();
}
}
}
Contract Source Code
File 119 of 124: StorageSlot.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol)// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.pragmasolidity ^0.8.20;/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC1967 implementation slot:
* ```solidity
* contract ERC1967 {
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(newImplementation.code.length > 0);
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*/libraryStorageSlot{
structAddressSlot {
address value;
}
structBooleanSlot {
bool value;
}
structBytes32Slot {
bytes32 value;
}
structUint256Slot {
uint256 value;
}
structStringSlot {
string value;
}
structBytesSlot {
bytes value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/functiongetAddressSlot(bytes32 slot) internalpurereturns (AddressSlot storage r) {
/// @solidity memory-safe-assemblyassembly {
r.slot:= slot
}
}
/**
* @dev Returns an `BooleanSlot` with member `value` located at `slot`.
*/functiongetBooleanSlot(bytes32 slot) internalpurereturns (BooleanSlot storage r) {
/// @solidity memory-safe-assemblyassembly {
r.slot:= slot
}
}
/**
* @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
*/functiongetBytes32Slot(bytes32 slot) internalpurereturns (Bytes32Slot storage r) {
/// @solidity memory-safe-assemblyassembly {
r.slot:= slot
}
}
/**
* @dev Returns an `Uint256Slot` with member `value` located at `slot`.
*/functiongetUint256Slot(bytes32 slot) internalpurereturns (Uint256Slot storage r) {
/// @solidity memory-safe-assemblyassembly {
r.slot:= slot
}
}
/**
* @dev Returns an `StringSlot` with member `value` located at `slot`.
*/functiongetStringSlot(bytes32 slot) internalpurereturns (StringSlot storage r) {
/// @solidity memory-safe-assemblyassembly {
r.slot:= slot
}
}
/**
* @dev Returns an `StringSlot` representation of the string storage pointer `store`.
*/functiongetStringSlot(stringstorage store) internalpurereturns (StringSlot storage r) {
/// @solidity memory-safe-assemblyassembly {
r.slot:= store.slot
}
}
/**
* @dev Returns an `BytesSlot` with member `value` located at `slot`.
*/functiongetBytesSlot(bytes32 slot) internalpurereturns (BytesSlot storage r) {
/// @solidity memory-safe-assemblyassembly {
r.slot:= slot
}
}
/**
* @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
*/functiongetBytesSlot(bytesstorage store) internalpurereturns (BytesSlot storage r) {
/// @solidity memory-safe-assemblyassembly {
r.slot:= store.slot
}
}
}
Contract Source Code
File 120 of 124: Strings.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol)pragmasolidity ^0.8.20;import {Math} from"./math/Math.sol";
import {SignedMath} from"./math/SignedMath.sol";
/**
* @dev String operations.
*/libraryStrings{
bytes16privateconstant HEX_DIGITS ="0123456789abcdef";
uint8privateconstant ADDRESS_LENGTH =20;
/**
* @dev The `value` string doesn't fit in the specified `length`.
*/errorStringsInsufficientHexLength(uint256 value, uint256 length);
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/functiontoString(uint256 value) internalpurereturns (stringmemory) {
unchecked {
uint256 length = Math.log10(value) +1;
stringmemory buffer =newstring(length);
uint256 ptr;
/// @solidity memory-safe-assemblyassembly {
ptr :=add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assemblyassembly {
mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))
}
value /=10;
if (value ==0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/functiontoStringSigned(int256 value) internalpurereturns (stringmemory) {
returnstring.concat(value <0 ? "-" : "", toString(SignedMath.abs(value)));
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/functiontoHexString(uint256 value) internalpurereturns (stringmemory) {
unchecked {
return toHexString(value, Math.log256(value) +1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/functiontoHexString(uint256 value, uint256 length) internalpurereturns (stringmemory) {
uint256 localValue = value;
bytesmemory buffer =newbytes(2* length +2);
buffer[0] ="0";
buffer[1] ="x";
for (uint256 i =2* length +1; i >1; --i) {
buffer[i] = HEX_DIGITS[localValue &0xf];
localValue >>=4;
}
if (localValue !=0) {
revert StringsInsufficientHexLength(value, length);
}
returnstring(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal
* representation.
*/functiontoHexString(address addr) internalpurereturns (stringmemory) {
return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);
}
/**
* @dev Returns true if the two strings are equal.
*/functionequal(stringmemory a, stringmemory b) internalpurereturns (bool) {
returnbytes(a).length==bytes(b).length&&keccak256(bytes(a)) ==keccak256(bytes(b));
}
}
File 123 of 124: WhitelistAddressCommunityCond.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;import {CondErrors} from'../libraries/CondErrors.sol';
import {CommunityCondBase} from'../../base/CommunityCondBase.sol';
/**
* @title WhitelistAddressCommunityCond
* @author OpenSocial Protocol
*
* @dev This contract specifies that whitelisted address can create communities.
*
*/contractWhitelistAddressCommunityCondisCommunityCondBase{
eventMaxCreationNumberSet(addressindexed to, uint256 maxCreationNumber, uint256 timestamp);
constructor(address osp) CommunityCondBase(osp) {}
mapping(address=>uint256) public maxCreationNumber;
mapping(address=>uint256) public creationCount;
/**
* @dev process create community,if the address is not whitelisted, revert.
*/function_processCreateCommunity(address to,
stringcalldata/*handle*/,
bytescalldata/*data*/) internaloverridenonPayable{
if (maxCreationNumber[to] <= creationCount[to]) {
revert CondErrors.NotWhitelisted();
}
creationCount[to]++;
}
/**
* @dev set the max creation number of an address, only openSocial governance can call this function.
*/functionsetMaxCreationNumber(address to, uint256 _maxCreationNumber) externalonlyOperation{
maxCreationNumber[to] = _maxCreationNumber;
emit MaxCreationNumberSet(to, _maxCreationNumber, block.timestamp);
}
/**
* @return The number of communities allowed to be created.
*/functionallowedCreationNumber(address to) externalviewreturns (uint256) {
return
maxCreationNumber[to] > creationCount[to]
? maxCreationNumber[to] - creationCount[to]
: 0;
}
}
Contract Source Code
File 124 of 124: draft-IERC6093.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)pragmasolidity ^0.8.20;/**
* @dev Standard ERC20 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens.
*/interfaceIERC20Errors{
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
*/errorERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/errorERC20InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/errorERC20InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
* @param spender Address that may be allowed to operate on tokens without being their owner.
* @param allowance Amount of tokens a `spender` is allowed to operate with.
* @param needed Minimum amount required to perform a transfer.
*/errorERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/errorERC20InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `spender` to be approved. Used in approvals.
* @param spender Address that may be allowed to operate on tokens without being their owner.
*/errorERC20InvalidSpender(address spender);
}
/**
* @dev Standard ERC721 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens.
*/interfaceIERC721Errors{
/**
* @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20.
* Used in balance queries.
* @param owner Address of the current owner of a token.
*/errorERC721InvalidOwner(address owner);
/**
* @dev Indicates a `tokenId` whose `owner` is the zero address.
* @param tokenId Identifier number of a token.
*/errorERC721NonexistentToken(uint256 tokenId);
/**
* @dev Indicates an error related to the ownership over a particular token. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param tokenId Identifier number of a token.
* @param owner Address of the current owner of a token.
*/errorERC721IncorrectOwner(address sender, uint256 tokenId, address owner);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/errorERC721InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/errorERC721InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param tokenId Identifier number of a token.
*/errorERC721InsufficientApproval(address operator, uint256 tokenId);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/errorERC721InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/errorERC721InvalidOperator(address operator);
}
/**
* @dev Standard ERC1155 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens.
*/interfaceIERC1155Errors{
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
* @param tokenId Identifier number of a token.
*/errorERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/errorERC1155InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/errorERC1155InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param owner Address of the current owner of a token.
*/errorERC1155MissingApprovalForAll(address operator, address owner);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/errorERC1155InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/errorERC1155InvalidOperator(address operator);
/**
* @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
* Used in batch transfers.
* @param idsLength Length of the array of token identifiers
* @param valuesLength Length of the array of token amounts
*/errorERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}