Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| 0x60806040 | 18936373 | 818 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
MultiERC1155Eligibility
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 1000000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
// import { console2 } from "forge-std/Test.sol"; // remove before deploy
import { HatsEligibilityModule, HatsModule } from "hats-module/HatsEligibilityModule.sol";
import { IERC1155 } from "@openzeppelin-contracts/contracts/token/ERC1155/IERC1155.sol";
/**
* @title ERC1155Eligibility
* @author pumpedlunch
* @notice A Hats Protocol eligibility module that checks if addresses holds at least one minimum balance of a set of
* ERC1155 token Ids
*/
contract MultiERC1155Eligibility is HatsEligibilityModule {
/*//////////////////////////////////////////////////////////////
PUBLIC CONSTANTS
//////////////////////////////////////////////////////////////*/
/**
* See: https://github.com/Hats-Protocol/hats-module/blob/main/src/HatsModule.sol
* -----------------------------------------------------------------+
* CLONE IMMUTABLE "STORAGE" |
* -----------------------------------------------------------------|
* Offset | Constant | Type | Length |
* -----------------------------------------------------------------|
* 0 | IMPLEMENTATION | address | 20 |
* 20 | HATS | address | 20 |
* 40 | hatId | uint256 | 32 |
* 72 | TOKEN_ADDRESS | address | 20 |
* 92 | ARRAY_LENGTH | uint256 | 32 |
* 124 | TOKEN_IDS | uint256 | ARRAY_LENGTH*32 |
* 124+(ARRAY_LENGTH) | MIN_BALANCES | uint256 | ARRAY_LENGTH*32 |
* -----------------------------------------------------------------+
*/
/// The address of the ERC1155 contract used to check eligibility
function TOKEN_ADDRESS() public pure returns (address) {
return _getArgAddress(72);
}
/// The length of the TOKEN_IDS & MIN_BALANCES arrays - these MUST be equal.
function ARRAY_LENGTH() public pure returns (uint256) {
return _getArgUint256(92);
}
/// The ERC1155token IDs that allow eligibility.
/// @dev NOTE: Wearer must satisfy only one token ID criteria for eligiblity.
/// @dev NOTE: the TOKEN_IDS length must match the MIN_BALANCES length
function TOKEN_IDS() public pure returns (uint256[] memory) {
return _getArgUint256Array(124, ARRAY_LENGTH());
}
/// The minimum balances required (for token ID in the corresponding index) for eligibility.
/// @dev NOTE: Wearer must satisfy only one token ID criteria for eligiblity
/// @dev NOTE: the TOKEN_IDS length must match the MIN_BALANCES length
function MIN_BALANCES() public pure returns (uint256[] memory) {
return _getArgUint256Array(124 + ARRAY_LENGTH() * 32, ARRAY_LENGTH());
}
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
/**
* @notice Deploy the ERC1155Eligibility implementation contract and set its version
* @dev This is only used to deploy the implementation contract, and should not be used to deploy clones
*/
constructor(string memory _version) HatsModule(_version) { }
/*//////////////////////////////////////////////////////////////
HATS ELIGIBILITY FUNCTION
//////////////////////////////////////////////////////////////*/
/**
* @inheritdoc HatsEligibilityModule
*/
function getWearerStatus(address _wearer, uint256 /*_hatId */ )
public
view
override
returns (bool eligible, bool standing)
{
uint256 len = ARRAY_LENGTH();
IERC1155 token = IERC1155(TOKEN_ADDRESS());
uint256[] memory tokenIds = TOKEN_IDS();
uint256[] memory minBalances = MIN_BALANCES();
for (uint256 i = 0; i < len;) {
eligible = token.balanceOf(_wearer, tokenIds[i]) >= minBalances[i];
if (eligible) break;
unchecked {
++i;
}
}
standing = true;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
// import { console2 } from "forge-std/Test.sol"; // remove before deploy
import { HatsModule } from "./HatsModule.sol";
import { IHatsEligibility } from "hats-protocol/Interfaces/IHatsEligibility.sol";
abstract contract HatsEligibilityModule is HatsModule, IHatsEligibility {
/**
* @dev Contracts that inherit from HatsEligibilityModule must call the HatsModule constructor:
* `HatsModule(_version)`.
*/
/*//////////////////////////////////////////////////////////////
HATS ELIGIBILITY FUNCTION
//////////////////////////////////////////////////////////////*/
/// @inheritdoc IHatsEligibility
function getWearerStatus(address _wearer, uint256 _hatId)
public
view
virtual
override
returns (bool eligible, bool standing)
{ }
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC1155/IERC1155.sol)
pragma solidity ^0.8.19;
import {IERC165} from "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC1155 compliant contract, as defined in the
* https://eips.ethereum.org/EIPS/eip-1155[EIP].
*/
interface IERC1155 is IERC165 {
/**
* @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`.
*/
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
/**
* @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
* transfers.
*/
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] values
);
/**
* @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
* `approved`.
*/
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
/**
* @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
*
* If an {URI} event was emitted for `id`, the standard
* https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
* returned by {IERC1155MetadataURI-uri}.
*/
event URI(string value, uint256 indexed id);
/**
* @dev Returns the value of tokens of token type `id` owned by `account`.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function balanceOf(address account, uint256 id) external view returns (uint256);
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
*
* Requirements:
*
* - `accounts` and `ids` must have the same length.
*/
function balanceOfBatch(
address[] calldata accounts,
uint256[] calldata ids
) external view returns (uint256[] memory);
/**
* @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
*
* Emits an {ApprovalForAll} event.
*
* Requirements:
*
* - `operator` cannot be the caller.
*/
function setApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
*
* See {setApprovalForAll}.
*/
function isApprovedForAll(address account, address operator) external view returns (bool);
/**
* @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.
*
* WARNING: This function can potentially allow a reentrancy attack when transferring tokens
* to an untrusted contract, when invoking {onERC1155Received} on the receiver.
* Ensure to follow the checks-effects-interactions pattern and consider employing
* reentrancy guards when interacting with untrusted contracts.
*
* Emits a {TransferSingle} event.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}.
* - `from` must have a balance of tokens of type `id` of at least `value` amount.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
* acceptance magic value.
*/
function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;
/**
* @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
*
*
* WARNING: This function can potentially allow a reentrancy attack when transferring tokens
* to an untrusted contract, when invoking {onERC1155BatchReceived} on the receiver.
* Ensure to follow the checks-effects-interactions pattern and consider employing
* reentrancy guards when interacting with untrusted contracts.
*
* Emits a {TransferBatch} event.
*
* Requirements:
*
* - `ids` and `values` must have the same length.
* - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
* acceptance magic value.
*/
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
// import { console2 } from "forge-std/Test.sol"; // remove before deploy
import { IHats } from "hats-protocol/Interfaces/IHats.sol";
import { IHatsModule } from "./interfaces/IHatsModule.sol";
import { Clone } from "solady/utils/Clone.sol";
import { Initializable } from "@openzeppelin-contracts/contracts/proxy/utils/Initializable.sol";
contract HatsModule is IHatsModule, Clone, Initializable {
/*//////////////////////////////////////////////////////////////
PUBLIC CONSTANTS
//////////////////////////////////////////////////////////////*/
/**
* This contract is a clone with immutable args, which means that it is deployed with a set of
* immutable storage variables (ie constants). Accessing these constants is cheaper than accessing
* regular storage variables (such as those set on initialization of a typical EIP-1167 clone),
* but requires a slightly different approach since they are read from calldata instead of storage.
*
* Below is a table of constants and their location.
*
* For more, see here: https://github.com/Saw-mon-and-Natalie/clones-with-immutable-args
*
* --------------------------------------------------------------------+
* CLONE IMMUTABLE "STORAGE" |
* --------------------------------------------------------------------|
* Offset | Constant | Type | Length | |
* --------------------------------------------------------------------|
* 0 | IMPLEMENTATION | address | 20 | |
* 20 | HATS | address | 20 | |
* 40 | hatId | uint256 | 32 | |
* 72+ | [other args] | [type] | [len] | |
* --------------------------------------------------------------------+
*/
/// @inheritdoc IHatsModule
function IMPLEMENTATION() public pure returns (address) {
return _getArgAddress(0);
}
/// @inheritdoc IHatsModule
function HATS() public pure returns (IHats) {
return IHats(_getArgAddress(20));
}
/// @inheritdoc IHatsModule
function hatId() public pure returns (uint256) {
return _getArgUint256(40);
}
/// @inheritdoc IHatsModule
string public version_;
/// @inheritdoc IHatsModule
function version() public view returns (string memory) {
return HatsModule(IMPLEMENTATION()).version_();
}
/*//////////////////////////////////////////////////////////////
INITIALIZER
//////////////////////////////////////////////////////////////*/
/// @inheritdoc IHatsModule
function setUp(bytes calldata _initData) public initializer {
_setUp(_initData);
}
/// @dev Override this function to set initial operational values for module instances
function _setUp(bytes calldata _initData) internal virtual { }
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
/// @notice Deploy the implementation contract and set its version
/// @dev This is only used to deploy the implementation contract, and should not be used to deploy clones
constructor(string memory _version) {
version_ = _version;
// prevent the implementation contract from being initialized
_disableInitializers();
}
}// SPDX-License-Identifier: AGPL-3.0
// Copyright (C) 2023 Haberdasher Labs
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
pragma solidity >=0.8.13;
interface IHatsEligibility {
/// @notice Returns the status of a wearer for a given hat
/// @dev If standing is false, eligibility MUST also be false
/// @param _wearer The address of the current or prospective Hat wearer
/// @param _hatId The id of the hat in question
/// @return eligible Whether the _wearer is eligible to wear the hat
/// @return standing Whether the _wearer is in goog standing
function getWearerStatus(address _wearer, uint256 _hatId) external view returns (bool eligible, bool standing);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.19;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: AGPL-3.0
// Copyright (C) 2023 Haberdasher Labs
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
pragma solidity >=0.8.13;
import "./IHatsIdUtilities.sol";
import "./HatsErrors.sol";
import "./HatsEvents.sol";
interface IHats is IHatsIdUtilities, HatsErrors, HatsEvents {
function mintTopHat(address _target, string memory _details, string memory _imageURI)
external
returns (uint256 topHatId);
function createHat(
uint256 _admin,
string calldata _details,
uint32 _maxSupply,
address _eligibility,
address _toggle,
bool _mutable,
string calldata _imageURI
) external returns (uint256 newHatId);
function batchCreateHats(
uint256[] calldata _admins,
string[] calldata _details,
uint32[] calldata _maxSupplies,
address[] memory _eligibilityModules,
address[] memory _toggleModules,
bool[] calldata _mutables,
string[] calldata _imageURIs
) external returns (bool success);
function getNextId(uint256 _admin) external view returns (uint256 nextId);
function mintHat(uint256 _hatId, address _wearer) external returns (bool success);
function batchMintHats(uint256[] calldata _hatIds, address[] calldata _wearers) external returns (bool success);
function setHatStatus(uint256 _hatId, bool _newStatus) external returns (bool toggled);
function checkHatStatus(uint256 _hatId) external returns (bool toggled);
function setHatWearerStatus(uint256 _hatId, address _wearer, bool _eligible, bool _standing)
external
returns (bool updated);
function checkHatWearerStatus(uint256 _hatId, address _wearer) external returns (bool updated);
function renounceHat(uint256 _hatId) external;
function transferHat(uint256 _hatId, address _from, address _to) external;
/*//////////////////////////////////////////////////////////////
HATS ADMIN FUNCTIONS
//////////////////////////////////////////////////////////////*/
function makeHatImmutable(uint256 _hatId) external;
function changeHatDetails(uint256 _hatId, string memory _newDetails) external;
function changeHatEligibility(uint256 _hatId, address _newEligibility) external;
function changeHatToggle(uint256 _hatId, address _newToggle) external;
function changeHatImageURI(uint256 _hatId, string memory _newImageURI) external;
function changeHatMaxSupply(uint256 _hatId, uint32 _newMaxSupply) external;
function requestLinkTopHatToTree(uint32 _topHatId, uint256 _newAdminHat) external;
function approveLinkTopHatToTree(
uint32 _topHatId,
uint256 _newAdminHat,
address _eligibility,
address _toggle,
string calldata _details,
string calldata _imageURI
) external;
function unlinkTopHatFromTree(uint32 _topHatId, address _wearer) external;
function relinkTopHatWithinTree(
uint32 _topHatDomain,
uint256 _newAdminHat,
address _eligibility,
address _toggle,
string calldata _details,
string calldata _imageURI
) external;
/*//////////////////////////////////////////////////////////////
VIEW FUNCTIONS
//////////////////////////////////////////////////////////////*/
function viewHat(uint256 _hatId)
external
view
returns (
string memory details,
uint32 maxSupply,
uint32 supply,
address eligibility,
address toggle,
string memory imageURI,
uint16 lastHatId,
bool mutable_,
bool active
);
function isWearerOfHat(address _user, uint256 _hatId) external view returns (bool isWearer);
function isAdminOfHat(address _user, uint256 _hatId) external view returns (bool isAdmin);
function isInGoodStanding(address _wearer, uint256 _hatId) external view returns (bool standing);
function isEligible(address _wearer, uint256 _hatId) external view returns (bool eligible);
function getHatEligibilityModule(uint256 _hatId) external view returns (address eligibility);
function getHatToggleModule(uint256 _hatId) external view returns (address toggle);
function getHatMaxSupply(uint256 _hatId) external view returns (uint32 maxSupply);
function hatSupply(uint256 _hatId) external view returns (uint32 supply);
function getImageURIForHat(uint256 _hatId) external view returns (string memory _uri);
function balanceOf(address wearer, uint256 hatId) external view returns (uint256 balance);
function balanceOfBatch(address[] calldata _wearers, uint256[] calldata _hatIds)
external
view
returns (uint256[] memory);
function uri(uint256 id) external view returns (string memory _uri);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import { IHats } from "hats-protocol/Interfaces/IHats.sol";
interface IHatsModule {
/// @notice Hats Protocol address
function HATS() external pure returns (IHats);
/// @notice The address of the implementation contract of which this instance is a clone
function IMPLEMENTATION() external pure returns (address);
/// @notice The hat id for which this HatsModule instance has been deployed
function hatId() external pure returns (uint256);
/**
* @notice Sets up this instance with initial operational values (`_initData`)
* @dev This function can only be called once, on initialization
* @param _initData Data to set up initial operational values for this instance
*/
function setUp(bytes memory _initData) external;
/// @notice The version of this HatsModule
/// @dev Used only for the implementation contract; for clones, use {version}
function version_() external view returns (string memory);
/// @notice The version of this HatsModule
function version() external view returns (string memory);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Class with helper read functions for clone with immutable args.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/Clone.sol)
/// @author Adapted from clones with immutable args by zefram.eth, Saw-mon & Natalie
/// (https://github.com/Saw-mon-and-Natalie/clones-with-immutable-args)
abstract contract Clone {
/// @dev Reads an immutable arg with type bytes.
function _getArgBytes(uint256 argOffset, uint256 length)
internal
pure
returns (bytes memory arg)
{
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := mload(0x40)
mstore(arg, length) // Store the length.
calldatacopy(add(arg, 0x20), add(offset, argOffset), length)
let o := add(add(arg, 0x20), length)
mstore(o, 0) // Zeroize the slot after the bytes.
mstore(0x40, add(o, 0x20)) // Allocate the memory.
}
}
/// @dev Reads an immutable arg with type address.
function _getArgAddress(uint256 argOffset) internal pure returns (address arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := shr(96, calldataload(add(offset, argOffset)))
}
}
/// @dev Reads a uint256 array stored in the immutable args.
function _getArgUint256Array(uint256 argOffset, uint256 length)
internal
pure
returns (uint256[] memory arg)
{
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := mload(0x40)
mstore(arg, length) // Store the length.
calldatacopy(add(arg, 0x20), add(offset, argOffset), shl(5, length))
mstore(0x40, add(add(arg, 0x20), shl(5, length))) // Allocate the memory.
}
}
/// @dev Reads a bytes32 array stored in the immutable args.
function _getArgBytes32Array(uint256 argOffset, uint256 length)
internal
pure
returns (bytes32[] memory arg)
{
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := mload(0x40)
mstore(arg, length) // Store the length.
calldatacopy(add(arg, 0x20), add(offset, argOffset), shl(5, length))
mstore(0x40, add(add(arg, 0x20), shl(5, length))) // Allocate the memory.
}
}
/// @dev Reads an immutable arg with type bytes32.
function _getArgBytes32(uint256 argOffset) internal pure returns (bytes32 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := calldataload(add(offset, argOffset))
}
}
/// @dev Reads an immutable arg with type uint256.
function _getArgUint256(uint256 argOffset) internal pure returns (uint256 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := calldataload(add(offset, argOffset))
}
}
/// @dev Reads an immutable arg with type uint248.
function _getArgUint248(uint256 argOffset) internal pure returns (uint248 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := shr(8, calldataload(add(offset, argOffset)))
}
}
/// @dev Reads an immutable arg with type uint240.
function _getArgUint240(uint256 argOffset) internal pure returns (uint240 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := shr(16, calldataload(add(offset, argOffset)))
}
}
/// @dev Reads an immutable arg with type uint232.
function _getArgUint232(uint256 argOffset) internal pure returns (uint232 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := shr(24, calldataload(add(offset, argOffset)))
}
}
/// @dev Reads an immutable arg with type uint224.
function _getArgUint224(uint256 argOffset) internal pure returns (uint224 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := shr(0x20, calldataload(add(offset, argOffset)))
}
}
/// @dev Reads an immutable arg with type uint216.
function _getArgUint216(uint256 argOffset) internal pure returns (uint216 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := shr(40, calldataload(add(offset, argOffset)))
}
}
/// @dev Reads an immutable arg with type uint208.
function _getArgUint208(uint256 argOffset) internal pure returns (uint208 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := shr(48, calldataload(add(offset, argOffset)))
}
}
/// @dev Reads an immutable arg with type uint200.
function _getArgUint200(uint256 argOffset) internal pure returns (uint200 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := shr(56, calldataload(add(offset, argOffset)))
}
}
/// @dev Reads an immutable arg with type uint192.
function _getArgUint192(uint256 argOffset) internal pure returns (uint192 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := shr(64, calldataload(add(offset, argOffset)))
}
}
/// @dev Reads an immutable arg with type uint184.
function _getArgUint184(uint256 argOffset) internal pure returns (uint184 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := shr(72, calldataload(add(offset, argOffset)))
}
}
/// @dev Reads an immutable arg with type uint176.
function _getArgUint176(uint256 argOffset) internal pure returns (uint176 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := shr(80, calldataload(add(offset, argOffset)))
}
}
/// @dev Reads an immutable arg with type uint168.
function _getArgUint168(uint256 argOffset) internal pure returns (uint168 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := shr(88, calldataload(add(offset, argOffset)))
}
}
/// @dev Reads an immutable arg with type uint160.
function _getArgUint160(uint256 argOffset) internal pure returns (uint160 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := shr(96, calldataload(add(offset, argOffset)))
}
}
/// @dev Reads an immutable arg with type uint152.
function _getArgUint152(uint256 argOffset) internal pure returns (uint152 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := shr(104, calldataload(add(offset, argOffset)))
}
}
/// @dev Reads an immutable arg with type uint144.
function _getArgUint144(uint256 argOffset) internal pure returns (uint144 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := shr(112, calldataload(add(offset, argOffset)))
}
}
/// @dev Reads an immutable arg with type uint136.
function _getArgUint136(uint256 argOffset) internal pure returns (uint136 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := shr(120, calldataload(add(offset, argOffset)))
}
}
/// @dev Reads an immutable arg with type uint128.
function _getArgUint128(uint256 argOffset) internal pure returns (uint128 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := shr(128, calldataload(add(offset, argOffset)))
}
}
/// @dev Reads an immutable arg with type uint120.
function _getArgUint120(uint256 argOffset) internal pure returns (uint120 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := shr(136, calldataload(add(offset, argOffset)))
}
}
/// @dev Reads an immutable arg with type uint112.
function _getArgUint112(uint256 argOffset) internal pure returns (uint112 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := shr(144, calldataload(add(offset, argOffset)))
}
}
/// @dev Reads an immutable arg with type uint104.
function _getArgUint104(uint256 argOffset) internal pure returns (uint104 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := shr(152, calldataload(add(offset, argOffset)))
}
}
/// @dev Reads an immutable arg with type uint96.
function _getArgUint96(uint256 argOffset) internal pure returns (uint96 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := shr(160, calldataload(add(offset, argOffset)))
}
}
/// @dev Reads an immutable arg with type uint88.
function _getArgUint88(uint256 argOffset) internal pure returns (uint88 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := shr(168, calldataload(add(offset, argOffset)))
}
}
/// @dev Reads an immutable arg with type uint80.
function _getArgUint80(uint256 argOffset) internal pure returns (uint80 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := shr(176, calldataload(add(offset, argOffset)))
}
}
/// @dev Reads an immutable arg with type uint72.
function _getArgUint72(uint256 argOffset) internal pure returns (uint72 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := shr(184, calldataload(add(offset, argOffset)))
}
}
/// @dev Reads an immutable arg with type uint64.
function _getArgUint64(uint256 argOffset) internal pure returns (uint64 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := shr(192, calldataload(add(offset, argOffset)))
}
}
/// @dev Reads an immutable arg with type uint56.
function _getArgUint56(uint256 argOffset) internal pure returns (uint56 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := shr(200, calldataload(add(offset, argOffset)))
}
}
/// @dev Reads an immutable arg with type uint48.
function _getArgUint48(uint256 argOffset) internal pure returns (uint48 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := shr(208, calldataload(add(offset, argOffset)))
}
}
/// @dev Reads an immutable arg with type uint40.
function _getArgUint40(uint256 argOffset) internal pure returns (uint40 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := shr(216, calldataload(add(offset, argOffset)))
}
}
/// @dev Reads an immutable arg with type uint32.
function _getArgUint32(uint256 argOffset) internal pure returns (uint32 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := shr(224, calldataload(add(offset, argOffset)))
}
}
/// @dev Reads an immutable arg with type uint24.
function _getArgUint24(uint256 argOffset) internal pure returns (uint24 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := shr(232, calldataload(add(offset, argOffset)))
}
}
/// @dev Reads an immutable arg with type uint16.
function _getArgUint16(uint256 argOffset) internal pure returns (uint16 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := shr(240, calldataload(add(offset, argOffset)))
}
}
/// @dev Reads an immutable arg with type uint8.
function _getArgUint8(uint256 argOffset) internal pure returns (uint8 arg) {
uint256 offset = _getImmutableArgsOffset();
/// @solidity memory-safe-assembly
assembly {
arg := shr(248, calldataload(add(offset, argOffset)))
}
}
/// @return offset The offset of the packed immutable args in calldata.
function _getImmutableArgsOffset() internal pure returns (uint256 offset) {
/// @solidity memory-safe-assembly
assembly {
offset := sub(calldatasize(), shr(240, calldataload(sub(calldatasize(), 2))))
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.19;
import {Address} from "../../utils/Address.sol";
/**
* @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();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev The contract is already initialized.
*/
error AlreadyInitialized();
/**
* @dev The contract is not initializing.
*/
error NotInitializing();
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 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 functions marked with `initializer` can be nested in the context of a
* constructor.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
if (!(isTopLevelCall && _initialized < 1) && !(address(this).code.length == 0 && _initialized == 1)) {
revert AlreadyInitialized();
}
_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 255 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint8 version) {
if (_initializing || _initialized >= version) {
revert AlreadyInitialized();
}
_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.
*/
modifier onlyInitializing() {
if (!_initializing) {
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() internal virtual {
if (_initializing) {
revert AlreadyInitialized();
}
if (_initialized != type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}// SPDX-License-Identifier: AGPL-3.0
// Copyright (C) 2023 Haberdasher Labs
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
pragma solidity >=0.8.13;
interface IHatsIdUtilities {
function buildHatId(uint256 _admin, uint16 _newHat) external pure returns (uint256 id);
function getHatLevel(uint256 _hatId) external view returns (uint32 level);
function getLocalHatLevel(uint256 _hatId) external pure returns (uint32 level);
function isTopHat(uint256 _hatId) external view returns (bool _topHat);
function isLocalTopHat(uint256 _hatId) external pure returns (bool _localTopHat);
function isValidHatId(uint256 _hatId) external view returns (bool validHatId);
function getAdminAtLevel(uint256 _hatId, uint32 _level) external view returns (uint256 admin);
function getAdminAtLocalLevel(uint256 _hatId, uint32 _level) external pure returns (uint256 admin);
function getTopHatDomain(uint256 _hatId) external view returns (uint32 domain);
function getTippyTopHatDomain(uint32 _topHatDomain) external view returns (uint32 domain);
function noCircularLinkage(uint32 _topHatDomain, uint256 _linkedAdmin) external view returns (bool notCircular);
function sameTippyTopHatDomain(uint32 _topHatDomain, uint256 _newAdminHat)
external
view
returns (bool sameDomain);
}// SPDX-License-Identifier: AGPL-3.0
// Copyright (C) 2023 Haberdasher Labs
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
pragma solidity >=0.8.13;
interface HatsErrors {
/// @notice Emitted when `user` is attempting to perform an action on `hatId` but is not wearing one of `hatId`'s admin hats
/// @dev Can be equivalent to `NotHatWearer(buildHatId(hatId))`, such as when emitted by `approveLinkTopHatToTree` or `relinkTopHatToTree`
error NotAdmin(address user, uint256 hatId);
/// @notice Emitted when attempting to perform an action as or for an account that is not a wearer of a given hat
error NotHatWearer();
/// @notice Emitted when attempting to perform an action that requires being either an admin or wearer of a given hat
error NotAdminOrWearer();
/// @notice Emitted when attempting to mint `hatId` but `hatId`'s maxSupply has been reached
error AllHatsWorn(uint256 hatId);
/// @notice Emitted when attempting to create a hat with a level 14 hat as its admin
error MaxLevelsReached();
/// @notice Emitted when an attempted hat id has empty intermediate level(s)
error InvalidHatId();
/// @notice Emitted when attempting to mint `hatId` to a `wearer` who is already wearing the hat
error AlreadyWearingHat(address wearer, uint256 hatId);
/// @notice Emitted when attempting to mint a non-existant hat
error HatDoesNotExist(uint256 hatId);
/// @notice Emmitted when attempting to mint or transfer a hat that is not active
error HatNotActive();
/// @notice Emitted when attempting to mint or transfer a hat to an ineligible wearer
error NotEligible();
/// @notice Emitted when attempting to check or set a hat's status from an account that is not that hat's toggle module
error NotHatsToggle();
/// @notice Emitted when attempting to check or set a hat wearer's status from an account that is not that hat's eligibility module
error NotHatsEligibility();
/// @notice Emitted when array arguments to a batch function have mismatching lengths
error BatchArrayLengthMismatch();
/// @notice Emitted when attempting to mutate or transfer an immutable hat
error Immutable();
/// @notice Emitted when attempting to change a hat's maxSupply to a value lower than its current supply
error NewMaxSupplyTooLow();
/// @notice Emitted when attempting to link a tophat to a new admin for which the tophat serves as an admin
error CircularLinkage();
/// @notice Emitted when attempting to link or relink a tophat to a separate tree
error CrossTreeLinkage();
/// @notice Emitted when attempting to link a tophat without a request
error LinkageNotRequested();
/// @notice Emitted when attempting to unlink a tophat that does not have a wearer
/// @dev This ensures that unlinking never results in a bricked tophat
error InvalidUnlink();
/// @notice Emmited when attempting to change a hat's eligibility or toggle module to the zero address
error ZeroAddress();
/// @notice Emmitted when attempting to change a hat's details or imageURI to a string with over 7000 bytes (~characters)
/// @dev This protects against a DOS attack where an admin iteratively extend's a hat's details or imageURI
/// to be so long that reading it exceeds the block gas limit, breaking `uri()` and `viewHat()`
error StringTooLong();
}// SPDX-License-Identifier: AGPL-3.0
// Copyright (C) 2023 Haberdasher Labs
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
pragma solidity >=0.8.13;
interface HatsEvents {
/// @notice Emitted when a new hat is created
/// @param id The id for the new hat
/// @param details A description of the Hat
/// @param maxSupply The total instances of the Hat that can be worn at once
/// @param eligibility The address that can report on the Hat wearer's status
/// @param toggle The address that can deactivate the Hat
/// @param mutable_ Whether the hat's properties are changeable after creation
/// @param imageURI The image uri for this hat and the fallback for its
event HatCreated(
uint256 id,
string details,
uint32 maxSupply,
address eligibility,
address toggle,
bool mutable_,
string imageURI
);
/// @notice Emitted when a hat wearer's standing is updated
/// @dev Eligibility is excluded since the source of truth for eligibility is the eligibility module and may change without a transaction
/// @param hatId The id of the wearer's hat
/// @param wearer The wearer's address
/// @param wearerStanding Whether the wearer is in good standing for the hat
event WearerStandingChanged(uint256 hatId, address wearer, bool wearerStanding);
/// @notice Emitted when a hat's status is updated
/// @param hatId The id of the hat
/// @param newStatus Whether the hat is active
event HatStatusChanged(uint256 hatId, bool newStatus);
/// @notice Emitted when a hat's details are updated
/// @param hatId The id of the hat
/// @param newDetails The updated details
event HatDetailsChanged(uint256 hatId, string newDetails);
/// @notice Emitted when a hat's eligibility module is updated
/// @param hatId The id of the hat
/// @param newEligibility The updated eligibiliy module
event HatEligibilityChanged(uint256 hatId, address newEligibility);
/// @notice Emitted when a hat's toggle module is updated
/// @param hatId The id of the hat
/// @param newToggle The updated toggle module
event HatToggleChanged(uint256 hatId, address newToggle);
/// @notice Emitted when a hat's mutability is updated
/// @param hatId The id of the hat
event HatMutabilityChanged(uint256 hatId);
/// @notice Emitted when a hat's maximum supply is updated
/// @param hatId The id of the hat
/// @param newMaxSupply The updated max supply
event HatMaxSupplyChanged(uint256 hatId, uint32 newMaxSupply);
/// @notice Emitted when a hat's image URI is updated
/// @param hatId The id of the hat
/// @param newImageURI The updated image URI
event HatImageURIChanged(uint256 hatId, string newImageURI);
/// @notice Emitted when a tophat linkage is requested by its admin
/// @param domain The domain of the tree tophat to link
/// @param newAdmin The tophat's would-be admin in the parent tree
event TopHatLinkRequested(uint32 domain, uint256 newAdmin);
/// @notice Emitted when a tophat is linked to a another tree
/// @param domain The domain of the newly-linked tophat
/// @param newAdmin The tophat's new admin in the parent tree
event TopHatLinked(uint32 domain, uint256 newAdmin);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.19;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev The ETH balance of the account is not enough to perform the operation.
*/
error AddressInsufficientBalance(address account);
/**
* @dev There's no code at `target` (it is not a contract).
*/
error AddressEmptyCode(address target);
/**
* @dev A call to an address target failed. The target may have reverted.
*/
error FailedInnerCall();
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert AddressInsufficientBalance(address(this));
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert FailedInnerCall();
}
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, defaultRevert);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with a
* `customRevert` function as a fallback when `target` reverts.
*
* Requirements:
*
* - `customRevert` must be a reverting function.
*/
function functionCall(
address target,
bytes memory data,
function() internal view customRevert
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, customRevert);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, defaultRevert);
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with a `customRevert` function as a fallback revert reason when `target` reverts.
*
* Requirements:
*
* - `customRevert` must be a reverting function.
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
function() internal view customRevert
) internal returns (bytes memory) {
if (address(this).balance < value) {
revert AddressInsufficientBalance(address(this));
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, customRevert);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, defaultRevert);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*/
function functionStaticCall(
address target,
bytes memory data,
function() internal view customRevert
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, customRevert);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, defaultRevert);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*/
function functionDelegateCall(
address target,
bytes memory data,
function() internal view customRevert
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, customRevert);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided `customRevert`) in case of unsuccessful call or if target was not a contract.
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
function() internal view customRevert
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check if target is a contract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
if (target.code.length == 0) {
revert AddressEmptyCode(target);
}
}
return returndata;
} else {
_revert(returndata, customRevert);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or with a default revert error.
*/
function verifyCallResult(bool success, bytes memory returndata) internal view returns (bytes memory) {
return verifyCallResult(success, returndata, defaultRevert);
}
/**
* @dev Same as {xref-Address-verifyCallResult-bool-bytes-}[`verifyCallResult`], but with a
* `customRevert` function as a fallback when `success` is `false`.
*
* Requirements:
*
* - `customRevert` must be a reverting function.
*/
function verifyCallResult(
bool success,
bytes memory returndata,
function() internal view customRevert
) internal view returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, customRevert);
}
}
/**
* @dev Default reverting function when no `customRevert` is provided in a function call.
*/
function defaultRevert() internal pure {
revert FailedInnerCall();
}
function _revert(bytes memory returndata, function() internal view customRevert) private view {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
customRevert();
revert FailedInnerCall();
}
}
}{
"remappings": [
"ds-test/=lib/forge-std/lib/ds-test/src/",
"forge-std/=lib/forge-std/src/",
"hats-protocol/=lib/hats-protocol/src/",
"hats-module/=lib/hats-module/src/",
"decentralist/=lib/decentralist/src/",
"@openzeppelin-contracts/=lib/openzeppelin-contracts/",
"solady/=lib/hats-module/lib/solady/src/",
"ERC1155/=lib/hats-protocol/lib/ERC1155/",
"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"openzeppelin/=lib/openzeppelin-contracts/contracts/",
"solbase/=lib/hats-protocol/lib/solbase/src/",
"utils/=lib/hats-protocol/lib/utils/"
],
"optimizer": {
"enabled": true,
"runs": 1000000
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "none",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "paris",
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"string","name":"_version","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"inputs":[],"name":"ARRAY_LENGTH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"HATS","outputs":[{"internalType":"contract IHats","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"IMPLEMENTATION","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"MIN_BALANCES","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"TOKEN_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"TOKEN_IDS","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_wearer","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"getWearerStatus","outputs":[{"internalType":"bool","name":"eligible","type":"bool"},{"internalType":"bool","name":"standing","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hatId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"_initData","type":"bytes"}],"name":"setUp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version_","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60806040523480156200001157600080fd5b5060405162000df138038062000df18339810160408190526200003491620000e9565b8060016200004382826200024d565b506200004e62000056565b505062000319565b600054610100900460ff16156200007f5760405162dc149f60e41b815260040160405180910390fd5b60005460ff90811614620000d1576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b634e487b7160e01b600052604160045260246000fd5b60006020808385031215620000fd57600080fd5b82516001600160401b03808211156200011557600080fd5b818501915085601f8301126200012a57600080fd5b8151818111156200013f576200013f620000d3565b604051601f8201601f19908116603f011681019083821181831017156200016a576200016a620000d3565b8160405282815288868487010111156200018357600080fd5b600093505b82841015620001a7578484018601518185018701529285019262000188565b600086848301015280965050505050505092915050565b600181811c90821680620001d357607f821691505b602082108103620001f457634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200024857600081815260208120601f850160051c81016020861015620002235750805b601f850160051c820191505b8181101562000244578281556001016200022f565b5050505b505050565b81516001600160401b03811115620002695762000269620000d3565b62000281816200027a8454620001be565b84620001fa565b602080601f831160018114620002b95760008415620002a05750858301515b600019600386901b1c1916600185901b17855562000244565b600085815260208120601f198616915b82811015620002ea57888601518255948401946001909101908401620002c9565b5085821015620003095787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b610ac880620003296000396000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c8063a02a4ad111610081578063dd1bb1fc1161005b578063dd1bb1fc14610257578063f5f58e001461025f578063fdc7e37a1461027457600080fd5b8063a02a4ad1146101e5578063a4f9edbf14610218578063bd6838721461022d57600080fd5b80633a4741bd116100b25780633a4741bd1461016757806354fd4d501461019a5780637150ef88146101af57600080fd5b806307ace2b5146100ce5780630bdf530014610110575b600080fd5b367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003602801355b6040519081526020015b60405180910390f35b367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036048013560601c5b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610107565b367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c610142565b6101a2610281565b604051610107919061077b565b367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560601c610142565b367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605c01356100fd565b61022b6102263660046107cc565b610340565b005b61024061023b36600461083e565b61047b565b604080519215158352901515602083015201610107565b6101a26105c7565b610267610655565b6040516101079190610883565b6102676106d1565b905090565b6060367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900335811c73ffffffffffffffffffffffffffffffffffffffff1663dd1bb1fc6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156102fa573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261027c91908101906108f6565b600054610100900460ff16158080156103605750600054600160ff909116105b15801561037e5750303b15801561037c575060005460ff166001145b155b156103b5576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561041357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b801561047657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b600080367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605c810135906048013560601c826104be6106d1565b905060006104ca610655565b905060005b848110156105b7578181815181106104e9576104e96109c1565b60200260200101518473ffffffffffffffffffffffffffffffffffffffff1662fdd58e8b86858151811061051f5761051f6109c1565b60200260200101516040518363ffffffff1660e01b815260040161056592919073ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b602060405180830381865afa158015610582573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105a691906109f0565b10159650866105b7576001016104cf565b5060019450505050509250929050565b600180546105d490610a09565b80601f016020809104026020016040519081016040528092919081815260200182805461060090610a09565b801561064d5780601f106106225761010080835404028352916020019161064d565b820191906000526020600020905b81548152906001019060200180831161063057829003601f168201915b505050505081565b606061027c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605c0135610693906020610a8b565b61069e90607c610aa8565b367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605c0135610707565b606061027c607c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605c01355b604051818152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003600583901b84820160208401378260051b60208301016040525092915050565b60005b8381101561077257818101518382015260200161075a565b50506000910152565b602081526000825180602084015261079a816040850160208701610757565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b600080602083850312156107df57600080fd5b823567ffffffffffffffff808211156107f757600080fd5b818501915085601f83011261080b57600080fd5b81358181111561081a57600080fd5b86602082850101111561082c57600080fd5b60209290920196919550909350505050565b6000806040838503121561085157600080fd5b823573ffffffffffffffffffffffffffffffffffffffff8116811461087557600080fd5b946020939093013593505050565b6020808252825182820181905260009190848201906040850190845b818110156108bb5783518352928401929184019160010161089f565b50909695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561090857600080fd5b815167ffffffffffffffff8082111561092057600080fd5b818401915084601f83011261093457600080fd5b815181811115610946576109466108c7565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561098c5761098c6108c7565b816040528281528760208487010111156109a557600080fd5b6109b6836020830160208801610757565b979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215610a0257600080fd5b5051919050565b600181811c90821680610a1d57607f821691505b602082108103610a56577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417610aa257610aa2610a5c565b92915050565b80820180821115610aa257610aa2610a5c56fea164736f6c6343000813000a00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000005302e322e30000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100c95760003560e01c8063a02a4ad111610081578063dd1bb1fc1161005b578063dd1bb1fc14610257578063f5f58e001461025f578063fdc7e37a1461027457600080fd5b8063a02a4ad1146101e5578063a4f9edbf14610218578063bd6838721461022d57600080fd5b80633a4741bd116100b25780633a4741bd1461016757806354fd4d501461019a5780637150ef88146101af57600080fd5b806307ace2b5146100ce5780630bdf530014610110575b600080fd5b367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003602801355b6040519081526020015b60405180910390f35b367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036048013560601c5b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610107565b367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90033560601c610142565b6101a2610281565b604051610107919061077b565b367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c90036014013560601c610142565b367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605c01356100fd565b61022b6102263660046107cc565b610340565b005b61024061023b36600461083e565b61047b565b604080519215158352901515602083015201610107565b6101a26105c7565b610267610655565b6040516101079190610883565b6102676106d1565b905090565b6060367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c900335811c73ffffffffffffffffffffffffffffffffffffffff1663dd1bb1fc6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156102fa573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261027c91908101906108f6565b600054610100900460ff16158080156103605750600054600160ff909116105b15801561037e5750303b15801561037c575060005460ff166001145b155b156103b5576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561041357600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b801561047657600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b600080367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605c810135906048013560601c826104be6106d1565b905060006104ca610655565b905060005b848110156105b7578181815181106104e9576104e96109c1565b60200260200101518473ffffffffffffffffffffffffffffffffffffffff1662fdd58e8b86858151811061051f5761051f6109c1565b60200260200101516040518363ffffffff1660e01b815260040161056592919073ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b602060405180830381865afa158015610582573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105a691906109f0565b10159650866105b7576001016104cf565b5060019450505050509250929050565b600180546105d490610a09565b80601f016020809104026020016040519081016040528092919081815260200182805461060090610a09565b801561064d5780601f106106225761010080835404028352916020019161064d565b820191906000526020600020905b81548152906001019060200180831161063057829003601f168201915b505050505081565b606061027c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605c0135610693906020610a8b565b61069e90607c610aa8565b367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605c0135610707565b606061027c607c367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003605c01355b604051818152367ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe81013560f01c9003600583901b84820160208401378260051b60208301016040525092915050565b60005b8381101561077257818101518382015260200161075a565b50506000910152565b602081526000825180602084015261079a816040850160208701610757565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b600080602083850312156107df57600080fd5b823567ffffffffffffffff808211156107f757600080fd5b818501915085601f83011261080b57600080fd5b81358181111561081a57600080fd5b86602082850101111561082c57600080fd5b60209290920196919550909350505050565b6000806040838503121561085157600080fd5b823573ffffffffffffffffffffffffffffffffffffffff8116811461087557600080fd5b946020939093013593505050565b6020808252825182820181905260009190848201906040850190845b818110156108bb5783518352928401929184019160010161089f565b50909695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561090857600080fd5b815167ffffffffffffffff8082111561092057600080fd5b818401915084601f83011261093457600080fd5b815181811115610946576109466108c7565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561098c5761098c6108c7565b816040528281528760208487010111156109a557600080fd5b6109b6836020830160208801610757565b979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060208284031215610a0257600080fd5b5051919050565b600181811c90821680610a1d57607f821691505b602082108103610a56577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417610aa257610aa2610a5c565b92915050565b80820180821115610aa257610aa2610a5c56fea164736f6c6343000813000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000005302e322e30000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _version (string): 0.2.0
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000005
Arg [2] : 302e322e30000000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.