Skip to content

Commit

Permalink
Merge pull request #275 from hackdays-io/faeture/HatsHatCreatorModule
Browse files Browse the repository at this point in the history
Feat/hats hat creator module
  • Loading branch information
yu23ki14 authored Jan 21, 2025
2 parents 52af295 + 03313db commit 26df6a1
Show file tree
Hide file tree
Showing 10 changed files with 531 additions and 13 deletions.
32 changes: 29 additions & 3 deletions pkgs/contract/contracts/bigbang/BigBang.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { IHats } from "../hats/src/Interfaces/IHats.sol";
import { IHatsModuleFactory } from "./IHatsModuleFactory.sol";
import { ISplitsCreatorFactory } from "../splitscreator/ISplitsCreatorFactory.sol";
import { HatsTimeFrameModule } from "../timeframe/HatsTimeFrameModule.sol";
import { HatsHatCreatorModule } from "../hatcreator/HatsHatCreatorModule.sol";
import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";

contract BigBang is OwnableUpgradeable {
Expand All @@ -16,6 +17,8 @@ contract BigBang is OwnableUpgradeable {

address public HatsTimeFrameModule_IMPL;

address public HatsHatCreatorModule_IMPL;

address public SplitsFactoryV2;

address public FractionToken;
Expand All @@ -26,6 +29,7 @@ contract BigBang is OwnableUpgradeable {
uint256 indexed topHatId,
uint256 hatterHatId,
address hatsTimeFrameModule,
address hatsHatCreatorModule,
address splitCreator
);

Expand All @@ -34,6 +38,7 @@ contract BigBang is OwnableUpgradeable {
* @param _hatsAddress Address of the hats protocol V1 contract.
* @param _hatsModuleFactory Address of the hats module factory contract.
* @param _hatsTimeFrameModule_IMPL Address of the hats time frame module implementation contract.
* @param _hatsHatCreatorModule_IMPL Address of the hats hat creator module implementation contract.
* @param _splitsCreatorFactory Address of the splits creator factory contract.
* @param _splitFactoryV2 Address of the split factory V2 contract.
* @param _fractionToken Address of the fraction token contract.
Expand All @@ -42,6 +47,7 @@ contract BigBang is OwnableUpgradeable {
address _hatsAddress,
address _hatsModuleFactory,
address _hatsTimeFrameModule_IMPL,
address _hatsHatCreatorModule_IMPL,
address _splitsCreatorFactory,
address _splitFactoryV2,
address _fractionToken
Expand All @@ -50,6 +56,7 @@ contract BigBang is OwnableUpgradeable {
Hats = IHats(_hatsAddress);
HatsModuleFactory = IHatsModuleFactory(_hatsModuleFactory);
HatsTimeFrameModule_IMPL = _hatsTimeFrameModule_IMPL;
HatsHatCreatorModule_IMPL = _hatsHatCreatorModule_IMPL;
SplitsCreatorFactory = ISplitsCreatorFactory(_splitsCreatorFactory);
SplitsFactoryV2 = _splitFactoryV2;
FractionToken = _fractionToken;
Expand Down Expand Up @@ -84,13 +91,22 @@ contract BigBang is OwnableUpgradeable {
uint256 hatterHatId = Hats.createHat(
topHatId, // _admin: The id of the Hat that will control who wears the newly created hat
_hatterHatDetails,
1,
2,
0x0000000000000000000000000000000000004A75,
0x0000000000000000000000000000000000004A75,
true,
_hatterHatImageURI
);

// 3. HatsHatCreatorModuleのデプロイ
address hatsHatCreatorModule = HatsModuleFactory.createHatsModule(
HatsHatCreatorModule_IMPL,
topHatId,
"",
abi.encode(_owner), // ownerを初期化データとして渡す
0
);

// 4. HatsTimeFrameModuleのデプロイ
address hatsTimeFrameModule = HatsModuleFactory.createHatsModule(
HatsTimeFrameModule_IMPL,
Expand All @@ -103,10 +119,13 @@ contract BigBang is OwnableUpgradeable {
// 5. HatsTimeFrameModuleにHatterHatをMint
Hats.mintHat(hatterHatId, hatsTimeFrameModule);

// 6. TopHatIdの権限を_ownerに譲渡
// 6. HatsHatCreatorModuleにHatterHatをMint
Hats.mintHat(hatterHatId, hatsHatCreatorModule);

// 7. TopHatIdの権限を_ownerに譲渡
Hats.transferHat(topHatId, address(this), _owner);

// 7. SplitCreatorをFactoryからデプロイ
// 8. SplitCreatorをFactoryからデプロイ
address splitCreator = SplitsCreatorFactory
.createSplitCreatorDeterministic(
topHatId,
Expand All @@ -123,6 +142,7 @@ contract BigBang is OwnableUpgradeable {
topHatId,
hatterHatId,
hatsTimeFrameModule,
hatsHatCreatorModule,
splitCreator
);

Expand Down Expand Up @@ -151,6 +171,12 @@ contract BigBang is OwnableUpgradeable {
HatsTimeFrameModule_IMPL = _hatsTimeFrameModuleImpl;
}

function setHatsHatCreatorModuleImpl(
address _hatsHatCreatorModuleImpl
) external onlyOwner {
HatsHatCreatorModule_IMPL = _hatsHatCreatorModuleImpl;
}

function setSplitsFactoryV2(address _splitsFactoryV2) external onlyOwner {
SplitsFactoryV2 = _splitsFactoryV2;
}
Expand Down
37 changes: 30 additions & 7 deletions pkgs/contract/contracts/bigbang/mock/BigBang_Mock_v2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@ import { IHats } from "../../hats/src/Interfaces/IHats.sol";
import { IHatsModuleFactory } from "../IHatsModuleFactory.sol";
import { ISplitsCreatorFactory } from "../../splitscreator/ISplitsCreatorFactory.sol";
import { HatsTimeFrameModule } from "../../timeframe/HatsTimeFrameModule.sol";
import { HatsHatCreatorModule } from "../../hatcreator/HatsHatCreatorModule.sol";
import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";

/**
* Upgradableになっている確認するための検証用BigBangコントラクト
*/
contract BigBang_Mock_v2 is OwnableUpgradeable {
IHats public Hats;

Expand All @@ -19,14 +17,17 @@ contract BigBang_Mock_v2 is OwnableUpgradeable {

address public HatsTimeFrameModule_IMPL;

address public HatsHatCreatorModule_IMPL;

address public SplitsFactoryV2;

address public FractionToken;

event Executed(
address indexed creator,
address indexed owner,
uint256 indexed topHatId,
uint256 indexed hatterHatId,
uint256 hatterHatId,
address hatsTimeFrameModule,
address splitCreator
);
Expand All @@ -36,6 +37,7 @@ contract BigBang_Mock_v2 is OwnableUpgradeable {
* @param _hatsAddress Address of the hats protocol V1 contract.
* @param _hatsModuleFactory Address of the hats module factory contract.
* @param _hatsTimeFrameModule_IMPL Address of the hats time frame module implementation contract.
* @param _hatsHatCreatorModule_IMPL Address of the hats hat creator module implementation contract.
* @param _splitsCreatorFactory Address of the splits creator factory contract.
* @param _splitFactoryV2 Address of the split factory V2 contract.
* @param _fractionToken Address of the fraction token contract.
Expand All @@ -44,6 +46,7 @@ contract BigBang_Mock_v2 is OwnableUpgradeable {
address _hatsAddress,
address _hatsModuleFactory,
address _hatsTimeFrameModule_IMPL,
address _hatsHatCreatorModule_IMPL,
address _splitsCreatorFactory,
address _splitFactoryV2,
address _fractionToken
Expand All @@ -52,6 +55,7 @@ contract BigBang_Mock_v2 is OwnableUpgradeable {
Hats = IHats(_hatsAddress);
HatsModuleFactory = IHatsModuleFactory(_hatsModuleFactory);
HatsTimeFrameModule_IMPL = _hatsTimeFrameModule_IMPL;
HatsHatCreatorModule_IMPL = _hatsHatCreatorModule_IMPL;
SplitsCreatorFactory = ISplitsCreatorFactory(_splitsCreatorFactory);
SplitsFactoryV2 = _splitFactoryV2;
FractionToken = _fractionToken;
Expand Down Expand Up @@ -86,13 +90,22 @@ contract BigBang_Mock_v2 is OwnableUpgradeable {
uint256 hatterHatId = Hats.createHat(
topHatId, // _admin: The id of the Hat that will control who wears the newly created hat
_hatterHatDetails,
1,
2,
0x0000000000000000000000000000000000004A75,
0x0000000000000000000000000000000000004A75,
true,
_hatterHatImageURI
);

// 3. HatsHatCreatorModuleのデプロイ
address hatsHatCreatorModule = HatsModuleFactory.createHatsModule(
HatsHatCreatorModule_IMPL,
topHatId,
"",
abi.encode(_owner), // ownerを初期化データとして渡す
0
);

// 4. HatsTimeFrameModuleのデプロイ
address hatsTimeFrameModule = HatsModuleFactory.createHatsModule(
HatsTimeFrameModule_IMPL,
Expand All @@ -105,10 +118,13 @@ contract BigBang_Mock_v2 is OwnableUpgradeable {
// 5. HatsTimeFrameModuleにHatterHatをMint
Hats.mintHat(hatterHatId, hatsTimeFrameModule);

// 6. TopHatIdの権限を_ownerに譲渡
// 6. HatsHatCreatorModuleにHatterHatをMint
Hats.mintHat(hatterHatId, hatsHatCreatorModule);

// 7. TopHatIdの権限を_ownerに譲渡
Hats.transferHat(topHatId, address(this), _owner);

// 7. SplitCreatorをFactoryからデプロイ
// 8. SplitCreatorをFactoryからデプロイ
address splitCreator = SplitsCreatorFactory
.createSplitCreatorDeterministic(
topHatId,
Expand All @@ -120,6 +136,7 @@ contract BigBang_Mock_v2 is OwnableUpgradeable {
);

emit Executed(
msg.sender,
_owner,
topHatId,
hatterHatId,
Expand Down Expand Up @@ -152,6 +169,12 @@ contract BigBang_Mock_v2 is OwnableUpgradeable {
HatsTimeFrameModule_IMPL = _hatsTimeFrameModuleImpl;
}

function setHatsHatCreatorModuleImpl(
address _hatsHatCreatorModuleImpl
) external onlyOwner {
HatsHatCreatorModule_IMPL = _hatsHatCreatorModuleImpl;
}

function setSplitsFactoryV2(address _splitsFactoryV2) external onlyOwner {
SplitsFactoryV2 = _splitsFactoryV2;
}
Expand Down
96 changes: 96 additions & 0 deletions pkgs/contract/contracts/hatcreator/HatsHatCreatorModule.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import {IHatsHatCreatorModule} from "./IHatsHatCreatorModule.sol";
import {HatsModule} from "../hats/module/HatsModule.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

contract HatsHatCreatorModule is HatsModule, Ownable, IHatsHatCreatorModule {
/// @dev Mapping to track addresses with hat creation authority
mapping(address => bool) public createHatAuthorities;

/**
* @dev Constructor to initialize the contract
* @param _version The version of the contract
* @param _tmpOwner The owner of the contract
*/
constructor(
string memory _version,
address _tmpOwner
) HatsModule(_version) Ownable(_tmpOwner) {}

/**
* @dev Initializes the contract, setting up the owner
* @param _initData The initialization data (encoded owner address)
*/
function _setUp(bytes calldata _initData) internal override {
address _owner = abi.decode(_initData, (address));
_transferOwnership(_owner);
createHatAuthorities[_owner] = true;
}

/**
* @notice Checks if an address has hat creation authority
* @param authority The address to check
* @return bool Whether the address has authority
*/
function hasCreateHatAuthority(address authority) public view returns (bool) {
return createHatAuthorities[authority];
}

/**
* @notice Grants hat creation authority to an address
* @param authority The address to grant authority to
*/
function grantCreateHatAuthority(address authority) external onlyOwner {
require(authority != address(0), "Invalid address");
require(!hasCreateHatAuthority(authority), "Already granted");

createHatAuthorities[authority] = true;
emit CreateHatAuthorityGranted(authority);
}

/**
* @notice Revokes hat creation authority from an address
* @param authority The address to revoke authority from
*/
function revokeCreateHatAuthority(address authority) external onlyOwner {
require(hasCreateHatAuthority(authority), "Not granted");

createHatAuthorities[authority] = false;
emit CreateHatAuthorityRevoked(authority);
}

/**
* @notice Creates a new hat
* @param _admin The ID of the admin (parent) hat
* @param _details The details of the hat
* @param _maxSupply The maximum supply of the hat
* @param _eligibility The address of the eligibility module
* @param _toggle The address of the toggle module
* @param _mutable Whether the hat's properties are changeable after creation
* @param _imageURI The image uri for this hat
* @return uint256 The ID of the created hat
*/
function createHat(
uint256 _admin,
string calldata _details,
uint32 _maxSupply,
address _eligibility,
address _toggle,
bool _mutable,
string calldata _imageURI
) external returns (uint256) {
require(hasCreateHatAuthority(msg.sender), "Not authorized");

return HATS().createHat(
_admin,
_details,
_maxSupply,
_eligibility,
_toggle,
_mutable,
_imageURI
);
}
}
54 changes: 54 additions & 0 deletions pkgs/contract/contracts/hatcreator/IHatsHatCreatorModule.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

interface IHatsHatCreatorModule {
/**
* @notice Grants hat creation authority to an address
* @param authority The address to grant authority to
*/
function grantCreateHatAuthority(address authority) external;

/**
* @notice Revokes hat creation authority from an address
* @param authority The address to revoke authority from
*/
function revokeCreateHatAuthority(address authority) external;

/**
* @notice Creates a new hat
* @param _admin The ID of the admin (parent) hat
* @param _details The details of the hat
* @param _maxSupply The maximum supply of the hat
* @param _eligibility The address of the eligibility module
* @param _toggle The address of the toggle module
* @param _mutable Whether the hat's properties are changeable after creation
* @param _imageURI The image uri for this hat
* @return hatId The ID of the created hat
*/
function createHat(
uint256 _admin,
string calldata _details,
uint32 _maxSupply,
address _eligibility,
address _toggle,
bool _mutable,
string calldata _imageURI
) external returns (uint256 hatId);

/**
* @notice Checks if an address has hat creation authority
* @param authority The address to check
* @return bool Whether the address has authority
*/
function hasCreateHatAuthority(address authority) external view returns (bool);

/**
* @notice Emitted when hat creation authority is granted
*/
event CreateHatAuthorityGranted(address indexed authority);

/**
* @notice Emitted when hat creation authority is revoked
*/
event CreateHatAuthorityRevoked(address indexed authority);
}
2 changes: 2 additions & 0 deletions pkgs/contract/helpers/deploy/BigBang.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const deployBigBang = async (params: {
hatsContractAddress: Address;
hatsModuleFacotryAddress: Address;
hatsTimeFrameModule_impl: Address;
hatsHatCreatorModule_impl: Address;
splitsCreatorFactoryAddress: Address;
splitsFactoryV2Address: Address;
fractionTokenAddress: Address;
Expand All @@ -30,6 +31,7 @@ export const deployBigBang = async (params: {
params.hatsContractAddress,
params.hatsModuleFacotryAddress,
params.hatsTimeFrameModule_impl,
params.hatsHatCreatorModule_impl,
params.splitsCreatorFactoryAddress,
params.splitsFactoryV2Address,
params.fractionTokenAddress,
Expand Down
Loading

0 comments on commit 26df6a1

Please sign in to comment.