From b28095be2318d489532afaddabddd447632a5ef8 Mon Sep 17 00:00:00 2001 From: Adam Gall Date: Wed, 9 Oct 2024 14:57:25 -0400 Subject: [PATCH] Copy in the FULL Hats interfaces --- contracts/interfaces/hats/full/HatsErrors.sol | 86 ++++++++ contracts/interfaces/hats/full/HatsEvents.sol | 92 ++++++++ contracts/interfaces/hats/full/IHats.sol | 205 ++++++++++++++++++ .../{ => full}/IHatsElectionEligibility.sol | 0 .../interfaces/hats/full/IHatsIdUtilities.sol | 68 ++++++ 5 files changed, 451 insertions(+) create mode 100644 contracts/interfaces/hats/full/HatsErrors.sol create mode 100644 contracts/interfaces/hats/full/HatsEvents.sol create mode 100644 contracts/interfaces/hats/full/IHats.sol rename contracts/interfaces/hats/{ => full}/IHatsElectionEligibility.sol (100%) create mode 100644 contracts/interfaces/hats/full/IHatsIdUtilities.sol diff --git a/contracts/interfaces/hats/full/HatsErrors.sol b/contracts/interfaces/hats/full/HatsErrors.sol new file mode 100644 index 00000000..b592529c --- /dev/null +++ b/contracts/interfaces/hats/full/HatsErrors.sol @@ -0,0 +1,86 @@ +// 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 . + +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(); +} diff --git a/contracts/interfaces/hats/full/HatsEvents.sol b/contracts/interfaces/hats/full/HatsEvents.sol new file mode 100644 index 00000000..817e4ec1 --- /dev/null +++ b/contracts/interfaces/hats/full/HatsEvents.sol @@ -0,0 +1,92 @@ +// 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 . + +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); +} diff --git a/contracts/interfaces/hats/full/IHats.sol b/contracts/interfaces/hats/full/IHats.sol new file mode 100644 index 00000000..5d0cc188 --- /dev/null +++ b/contracts/interfaces/hats/full/IHats.sol @@ -0,0 +1,205 @@ +// 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 . + +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); +} diff --git a/contracts/interfaces/hats/IHatsElectionEligibility.sol b/contracts/interfaces/hats/full/IHatsElectionEligibility.sol similarity index 100% rename from contracts/interfaces/hats/IHatsElectionEligibility.sol rename to contracts/interfaces/hats/full/IHatsElectionEligibility.sol diff --git a/contracts/interfaces/hats/full/IHatsIdUtilities.sol b/contracts/interfaces/hats/full/IHatsIdUtilities.sol new file mode 100644 index 00000000..dcf640fd --- /dev/null +++ b/contracts/interfaces/hats/full/IHatsIdUtilities.sol @@ -0,0 +1,68 @@ +// 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 . + +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); +}