From 167cb2e7087fae783d727e882be630b2c8c628ff Mon Sep 17 00:00:00 2001 From: yu23ki14 Date: Fri, 6 Dec 2024 18:00:42 +0900 Subject: [PATCH 1/2] remove erc2771 --- .../contracts/ERC2771ContextUpgradeable.sol | 73 --- pkgs/contract/contracts/Lock.sol | 34 -- pkgs/contract/contracts/bigbang/BigBang.sol | 33 +- .../bigbang/mock/BigBang_Mock_v2.sol | 29 +- .../contracts/fractiontoken/FractionToken.sol | 27 +- .../mock/FractionToken_Mock_v2.sol | 43 +- .../splitscreator/ISplitsCreatorFactory.sol | 1 - .../contracts/splitscreator/SplitsCreator.sol | 428 +++++++++--------- .../splitscreator/SplitsCreatorFactory.sol | 36 +- .../timeframe/HatsTimeFrameModule.sol | 58 +-- pkgs/contract/helpers/deploy/BigBang.ts | 2 - pkgs/contract/helpers/deploy/FractionToken.ts | 5 +- pkgs/contract/helpers/deploy/Hats.ts | 6 +- pkgs/contract/helpers/deploy/Splits.ts | 10 +- pkgs/contract/helpers/upgrade/bigbang.ts | 3 +- pkgs/contract/test/BigBang.ts | 14 +- pkgs/contract/test/FractionToken.ts | 87 ++-- pkgs/contract/test/HatsTimeFrameModule.ts | 37 +- pkgs/contract/test/IntegrationTest.ts | 17 +- pkgs/contract/test/SplitsCreator.ts | 18 +- 20 files changed, 346 insertions(+), 615 deletions(-) delete mode 100644 pkgs/contract/contracts/ERC2771ContextUpgradeable.sol delete mode 100644 pkgs/contract/contracts/Lock.sol diff --git a/pkgs/contract/contracts/ERC2771ContextUpgradeable.sol b/pkgs/contract/contracts/ERC2771ContextUpgradeable.sol deleted file mode 100644 index a01b797..0000000 --- a/pkgs/contract/contracts/ERC2771ContextUpgradeable.sol +++ /dev/null @@ -1,73 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.7.0) (metatx/ERC2771Context.sol) - -pragma solidity ^0.8.24; - -import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; -import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; - -/** - * @dev Context variant with ERC2771 support. - */ -abstract contract ERC2771ContextUpgradeable is - Initializable, - ContextUpgradeable -{ - address private _trustedForwarder; - - function __ERC2771Context_init(address trustedForwarder) - internal - onlyInitializing - { - __Context_init_unchained(); - _trustedForwarder = trustedForwarder; - } - - function isTrustedForwarder(address forwarder) - public - view - virtual - returns (bool) - { - return forwarder == _trustedForwarder; - } - - function _msgSender() - internal - view - virtual - override - returns (address sender) - { - if (isTrustedForwarder(msg.sender)) { - // The assembly code is more direct than the Solidity version using `abi.decode`. - /// @solidity memory-safe-assembly - assembly { - sender := shr(96, calldataload(sub(calldatasize(), 20))) - } - } else { - return super._msgSender(); - } - } - - function _msgData() - internal - view - virtual - override - returns (bytes calldata) - { - if (isTrustedForwarder(msg.sender)) { - return msg.data[:msg.data.length - 20]; - } else { - return super._msgData(); - } - } - - /** - * @dev This empty reserved space is put in place to allow future versions to add new - * variables without shifting down storage in the inheritance chain. - * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps - */ - uint256[50] private __gap; -} \ No newline at end of file diff --git a/pkgs/contract/contracts/Lock.sol b/pkgs/contract/contracts/Lock.sol deleted file mode 100644 index e6e85c3..0000000 --- a/pkgs/contract/contracts/Lock.sol +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.24; - -// Uncomment this line to use console.log -// import "hardhat/console.sol"; - -contract Lock { - uint public unlockTime; - address payable public owner; - - event Withdrawal(uint amount, uint when); - - constructor(uint _unlockTime) payable { - require( - block.timestamp < _unlockTime, - "Unlock time should be in the future" - ); - - unlockTime = _unlockTime; - owner = payable(msg.sender); - } - - function withdraw() public { - // Uncomment this line, and the import of "hardhat/console.sol", to print a log in your terminal - // console.log("Unlock time is %o and block timestamp is %o", unlockTime, block.timestamp); - - require(block.timestamp >= unlockTime, "You can't withdraw yet"); - require(msg.sender == owner, "You aren't the owner"); - - emit Withdrawal(address(this).balance, block.timestamp); - - owner.transfer(address(this).balance); - } -} \ No newline at end of file diff --git a/pkgs/contract/contracts/bigbang/BigBang.sol b/pkgs/contract/contracts/bigbang/BigBang.sol index 391d0af..18c048b 100644 --- a/pkgs/contract/contracts/bigbang/BigBang.sol +++ b/pkgs/contract/contracts/bigbang/BigBang.sol @@ -5,10 +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 "./../ERC2771ContextUpgradeable.sol"; import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; -contract BigBang is ERC2771ContextUpgradeable, OwnableUpgradeable { +contract BigBang is OwnableUpgradeable { IHats public Hats; IHatsModuleFactory public HatsModuleFactory; @@ -22,16 +21,16 @@ contract BigBang is ERC2771ContextUpgradeable, OwnableUpgradeable { address public FractionToken; event Executed( + address indexed creator, address indexed owner, uint256 indexed topHatId, - uint256 indexed hatterHatId, + uint256 hatterHatId, address hatsTimeFrameModule, address splitCreator ); /** * @dev Constructor to initialize the trusted forwarder. - * @param _trustedForwarder Address of the trusted forwarder contract. * @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. @@ -40,7 +39,6 @@ contract BigBang is ERC2771ContextUpgradeable, OwnableUpgradeable { * @param _fractionToken Address of the fraction token contract. */ function initialize( - address _trustedForwarder, address _hatsAddress, address _hatsModuleFactory, address _hatsTimeFrameModule_IMPL, @@ -49,7 +47,6 @@ contract BigBang is ERC2771ContextUpgradeable, OwnableUpgradeable { address _fractionToken ) public initializer { __Ownable_init(_msgSender()); - __ERC2771Context_init(address(_trustedForwarder)); Hats = IHats(_hatsAddress); HatsModuleFactory = IHatsModuleFactory(_hatsModuleFactory); HatsTimeFrameModule_IMPL = _hatsTimeFrameModule_IMPL; @@ -65,7 +62,6 @@ contract BigBang is ERC2771ContextUpgradeable, OwnableUpgradeable { * @param _topHatImageURI The image URI of the topHat. * @param _hatterHatDetails The details of the hatterHat. * @param _hatterHatImageURI The image URI of the hatterHat. - * @param _trustedForwarder The address of the trusted forwarder. * @return topHatId The ID used for navigating to the ProjectTop page after project creation. */ function bigbang( @@ -73,8 +69,7 @@ contract BigBang is ERC2771ContextUpgradeable, OwnableUpgradeable { string calldata _topHatDetails, string calldata _topHatImageURI, string calldata _hatterHatDetails, - string calldata _hatterHatImageURI, - address _trustedForwarder + string calldata _hatterHatImageURI ) external returns (uint256) { // 1. TopHatのMint @@ -115,7 +110,6 @@ contract BigBang is ERC2771ContextUpgradeable, OwnableUpgradeable { address splitCreator = SplitsCreatorFactory .createSplitCreatorDeterministic( topHatId, - _trustedForwarder, address(Hats), SplitsFactoryV2, hatsTimeFrameModule, @@ -124,6 +118,7 @@ contract BigBang is ERC2771ContextUpgradeable, OwnableUpgradeable { ); emit Executed( + msg.sender, _owner, topHatId, hatterHatId, @@ -163,22 +158,4 @@ contract BigBang is ERC2771ContextUpgradeable, OwnableUpgradeable { function setFractionToken(address _fractionToken) external onlyOwner { FractionToken = _fractionToken; } - - function _msgSender() - internal - view - override(ERC2771ContextUpgradeable, ContextUpgradeable) - returns (address sender) - { - return super._msgSender(); - } - - function _msgData() - internal - view - override(ERC2771ContextUpgradeable, ContextUpgradeable) - returns (bytes calldata) - { - return super._msgData(); - } } diff --git a/pkgs/contract/contracts/bigbang/mock/BigBang_Mock_v2.sol b/pkgs/contract/contracts/bigbang/mock/BigBang_Mock_v2.sol index 4320aa8..87bc40b 100644 --- a/pkgs/contract/contracts/bigbang/mock/BigBang_Mock_v2.sol +++ b/pkgs/contract/contracts/bigbang/mock/BigBang_Mock_v2.sol @@ -5,13 +5,12 @@ 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 "../../ERC2771ContextUpgradeable.sol"; import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; /** * Upgradableになっている確認するための検証用BigBangコントラクト */ -contract BigBang_Mock_v2 is ERC2771ContextUpgradeable, OwnableUpgradeable { +contract BigBang_Mock_v2 is OwnableUpgradeable { IHats public Hats; IHatsModuleFactory public HatsModuleFactory; @@ -34,7 +33,6 @@ contract BigBang_Mock_v2 is ERC2771ContextUpgradeable, OwnableUpgradeable { /** * @dev Constructor to initialize the trusted forwarder. - * @param _trustedForwarder Address of the trusted forwarder contract. * @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. @@ -43,7 +41,6 @@ contract BigBang_Mock_v2 is ERC2771ContextUpgradeable, OwnableUpgradeable { * @param _fractionToken Address of the fraction token contract. */ function initialize( - address _trustedForwarder, address _hatsAddress, address _hatsModuleFactory, address _hatsTimeFrameModule_IMPL, @@ -52,7 +49,6 @@ contract BigBang_Mock_v2 is ERC2771ContextUpgradeable, OwnableUpgradeable { address _fractionToken ) public initializer { __Ownable_init(_msgSender()); - __ERC2771Context_init(address(_trustedForwarder)); Hats = IHats(_hatsAddress); HatsModuleFactory = IHatsModuleFactory(_hatsModuleFactory); HatsTimeFrameModule_IMPL = _hatsTimeFrameModule_IMPL; @@ -68,7 +64,6 @@ contract BigBang_Mock_v2 is ERC2771ContextUpgradeable, OwnableUpgradeable { * @param _topHatImageURI The image URI of the topHat. * @param _hatterHatDetails The details of the hatterHat. * @param _hatterHatImageURI The image URI of the hatterHat. - * @param _trustedForwarder The address of the trusted forwarder. * @return topHatId The ID used for navigating to the ProjectTop page after project creation. */ function bigbang( @@ -76,8 +71,7 @@ contract BigBang_Mock_v2 is ERC2771ContextUpgradeable, OwnableUpgradeable { string calldata _topHatDetails, string calldata _topHatImageURI, string calldata _hatterHatDetails, - string calldata _hatterHatImageURI, - address _trustedForwarder + string calldata _hatterHatImageURI ) external returns (uint256) { // 1. TopHatのMint @@ -118,7 +112,6 @@ contract BigBang_Mock_v2 is ERC2771ContextUpgradeable, OwnableUpgradeable { address splitCreator = SplitsCreatorFactory .createSplitCreatorDeterministic( topHatId, - _trustedForwarder, address(Hats), SplitsFactoryV2, hatsTimeFrameModule, @@ -167,24 +160,6 @@ contract BigBang_Mock_v2 is ERC2771ContextUpgradeable, OwnableUpgradeable { FractionToken = _fractionToken; } - function _msgSender() - internal - view - override(ERC2771ContextUpgradeable, ContextUpgradeable) - returns (address sender) - { - return super._msgSender(); - } - - function _msgData() - internal - view - override(ERC2771ContextUpgradeable, ContextUpgradeable) - returns (bytes calldata) - { - return super._msgData(); - } - /** * 検証用に追加した関数 */ diff --git a/pkgs/contract/contracts/fractiontoken/FractionToken.sol b/pkgs/contract/contracts/fractiontoken/FractionToken.sol index cd6a282..2615a38 100644 --- a/pkgs/contract/contracts/fractiontoken/FractionToken.sol +++ b/pkgs/contract/contracts/fractiontoken/FractionToken.sol @@ -1,11 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.24; -import { ERC1155Upgradeable, ContextUpgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol"; +import { ERC1155Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol"; import { IHats } from "../hats/src/Interfaces/IHats.sol"; -import { ERC2771ContextUpgradeable } from "./../ERC2771ContextUpgradeable.sol"; -contract FractionToken is ERC1155Upgradeable, ERC2771ContextUpgradeable { +contract FractionToken is ERC1155Upgradeable { uint256 public TOKEN_SUPPLY; mapping(uint256 => address[]) private tokenRecipients; @@ -15,11 +14,9 @@ contract FractionToken is ERC1155Upgradeable, ERC2771ContextUpgradeable { function initialize( string memory _uri, uint256 _tokenSupply, - address _hatsAddress, - address _trustedForwarderAddress + address _hatsAddress ) public initializer { __ERC1155_init(_uri); - __ERC2771Context_init(address(_trustedForwarderAddress)); hatsContract = IHats(_hatsAddress); TOKEN_SUPPLY = _tokenSupply; } @@ -191,22 +188,4 @@ contract FractionToken is ERC1155Upgradeable, ERC2771ContextUpgradeable { ) public view override(ERC1155Upgradeable) returns (string memory) { return super.uri(tokenId); } - - function _msgSender() - internal - view - override(ERC2771ContextUpgradeable, ContextUpgradeable) - returns (address sender) - { - return super._msgSender(); - } - - function _msgData() - internal - view - override(ERC2771ContextUpgradeable, ContextUpgradeable) - returns (bytes calldata) - { - return super._msgData(); - } } diff --git a/pkgs/contract/contracts/fractiontoken/mock/FractionToken_Mock_v2.sol b/pkgs/contract/contracts/fractiontoken/mock/FractionToken_Mock_v2.sol index 350b762..df4e677 100644 --- a/pkgs/contract/contracts/fractiontoken/mock/FractionToken_Mock_v2.sol +++ b/pkgs/contract/contracts/fractiontoken/mock/FractionToken_Mock_v2.sol @@ -4,10 +4,8 @@ pragma solidity ^0.8.24; import "@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; import { IHats } from "../../hats/src/Interfaces/IHats.sol"; -import "./../../ERC2771ContextUpgradeable.sol"; - -contract FractionToken_Mock_v2 is ERC1155Upgradeable, ERC2771ContextUpgradeable { +contract FractionToken_Mock_v2 is ERC1155Upgradeable { uint256 public TOKEN_SUPPLY; mapping(uint256 => address[]) private tokenRecipients; @@ -17,19 +15,14 @@ contract FractionToken_Mock_v2 is ERC1155Upgradeable, ERC2771ContextUpgradeable function initialize( string memory _uri, uint256 _tokenSupply, - address _hatsAddress, - address _trustedForwarderAddress + address _hatsAddress ) public initializer { __ERC1155_init(_uri); - __ERC2771Context_init(address(_trustedForwarderAddress)); hatsContract = IHats(_hatsAddress); TOKEN_SUPPLY = _tokenSupply; } - function mintInitialSupply( - uint256 hatId, - address account - ) public { + function mintInitialSupply(uint256 hatId, address account) public { require( _hasHatRole(account, hatId), "This account does not have the role" @@ -54,18 +47,14 @@ contract FractionToken_Mock_v2 is ERC1155Upgradeable, ERC2771ContextUpgradeable } } - function mint( - uint256 hatId, - address account, - uint256 amount - ) public { + function mint(uint256 hatId, address account, uint256 amount) public { uint256 tokenId = getTokenId(hatId, account); require( tokenRecipients[tokenId].length > 0, "This account has not received the initial supply" ); - + require( _msgSender() == tokenRecipients[tokenId][0], "Only the first recipient can additionally mint" @@ -154,9 +143,7 @@ contract FractionToken_Mock_v2 is ERC1155Upgradeable, ERC2771ContextUpgradeable return balance > 0; } - function _hasHatAuthority( - uint256 hatId - ) private view returns (bool) { + function _hasHatAuthority(uint256 hatId) private view returns (bool) { uint32 hatLevel = hatsContract.getHatLevel(hatId); uint256 parentHatId = hatsContract.getAdminAtLevel(hatId, hatLevel - 1); @@ -205,24 +192,6 @@ contract FractionToken_Mock_v2 is ERC1155Upgradeable, ERC2771ContextUpgradeable return super.uri(tokenId); } - function _msgSender() - internal - view - override(ERC2771ContextUpgradeable, ContextUpgradeable) - returns (address sender) - { - return super._msgSender(); - } - - function _msgData() - internal - view - override(ERC2771ContextUpgradeable, ContextUpgradeable) - returns (bytes calldata) - { - return super._msgData(); - } - function _contextSuffixLength() internal view diff --git a/pkgs/contract/contracts/splitscreator/ISplitsCreatorFactory.sol b/pkgs/contract/contracts/splitscreator/ISplitsCreatorFactory.sol index 48e4343..9234d79 100644 --- a/pkgs/contract/contracts/splitscreator/ISplitsCreatorFactory.sol +++ b/pkgs/contract/contracts/splitscreator/ISplitsCreatorFactory.sol @@ -7,7 +7,6 @@ interface ISplitsCreatorFactory { function createSplitCreatorDeterministic( uint256 _topHatId, - address _trustedForwarder, address _hats, address _splitFactoryV2, address _hatsTimeFrameModule, diff --git a/pkgs/contract/contracts/splitscreator/SplitsCreator.sol b/pkgs/contract/contracts/splitscreator/SplitsCreator.sol index 06c928c..fc75aed 100644 --- a/pkgs/contract/contracts/splitscreator/SplitsCreator.sol +++ b/pkgs/contract/contracts/splitscreator/SplitsCreator.sol @@ -8,224 +8,218 @@ import { ISplitFactoryV2 } from "../splits/interfaces/ISplitFactoryV2.sol"; import { SplitV2Lib } from "../splits/libraries/SplitV2.sol"; import { IFractionToken } from "../fractiontoken/IFractionToken.sol"; import { IHatsTimeFrameModule } from "../timeframe/IHatsTimeFrameModule.sol"; -import { ERC2771Context } from "@openzeppelin/contracts/metatx/ERC2771Context.sol"; import { Clone } from "solady/src/utils/Clone.sol"; contract SplitsCreator is ISplitsCreator, Clone { - function TRUSTED_FORWARDER() public pure returns (address) { - return _getArgAddress(12); - } - - function HATS() public pure returns (IHats) { - return IHats(_getArgAddress(44)); - } - - function SPLIT_FACTORY_V2() public pure returns (ISplitFactoryV2) { - return ISplitFactoryV2(_getArgAddress(76)); - } - - function HATS_TIME_FRAME_MODULE() - public - pure - returns (IHatsTimeFrameModule) - { - return IHatsTimeFrameModule(_getArgAddress(108)); - } - - function FRACTION_TOKEN() public pure returns (IFractionToken) { - return IFractionToken(_getArgAddress(140)); - } - - /** - * @notice Creates a new split contract based on the provided splits information. - * @param _splitsInfo An array of SplitsInfo structs containing details about roles, wearers, and multipliers. - * @return The address of the newly created split contract. - */ - function create( - SplitsInfo[] memory _splitsInfo - ) external returns (address) { - ( - address[] memory shareHolders, - uint256[] memory allocations, - uint256 totalAllocation - ) = _calculateAllocations(_splitsInfo); - - SplitV2Lib.Split memory _splitParams = SplitV2Lib.Split({ - recipients: shareHolders, - allocations: allocations, - totalAllocation: totalAllocation, - distributionIncentive: 0 - }); - - address split = SPLIT_FACTORY_V2().createSplitDeterministic( - _splitParams, - address(this), - msg.sender, - _generateSalt(_splitsInfo) - ); - - emit SplitsCreated(split, shareHolders, allocations, totalAllocation); - - return split; - } - - /** - * @notice Previews the allocations without creating a split contract. - * @param _splitsInfo An array of SplitsInfo structs containing details about roles, wearers, and multipliers. - * @return shareHolders An array of shareholder addresses. - * @return percentages Corresponding allocation percentages (with 18 decimals) for each shareholder. - */ - function preview( - SplitsInfo[] memory _splitsInfo - ) - external - view - returns ( - address[] memory shareHolders, - uint256[] memory percentages - ) - { - ( - address[] memory _shareHolders, - uint256[] memory allocations, - uint256 totalAllocation - ) = _calculateAllocations(_splitsInfo); - - percentages = new uint256[](allocations.length); - for (uint256 i = 0; i < allocations.length; i++) { - percentages[i] = (allocations[i] * 1e18) / totalAllocation; - } - - return (_shareHolders, percentages); - } - - /** - * @dev Internal function to calculate allocations for shareholders. - * @param _splitsInfo An array of SplitsInfo structs containing details about roles, wearers, and multipliers. - * @return shareHolders An array of shareholder addresses. - * @return allocations Corresponding allocations for each shareholder. - * @return totalAllocation Sum of all allocations. - */ - function _calculateAllocations( - SplitsInfo[] memory _splitsInfo - ) - internal - view - returns ( - address[] memory shareHolders, - uint256[] memory allocations, - uint256 totalAllocation - ) - { - uint256 numOfShareHolders = 0; - for (uint256 i = 0; i < _splitsInfo.length; i++) { - SplitsInfo memory _splitInfo = _splitsInfo[i]; - for (uint256 si = 0; si < _splitInfo.wearers.length; si++) { - uint256 tokenId = FRACTION_TOKEN().getTokenId( - _splitInfo.hatId, - _splitInfo.wearers[si] - ); - address[] memory recipients = FRACTION_TOKEN() - .getTokenRecipients(tokenId); - numOfShareHolders += recipients.length; - } - } - - shareHolders = new address[](numOfShareHolders); - address[] memory wearers = new address[](numOfShareHolders); - uint256[] memory hatIdsOfShareHolders = new uint256[](numOfShareHolders); - uint256[] memory roleMultipliersOfShareHolders = new uint256[]( - numOfShareHolders - ); - uint256[] memory hatsTimeFrameMultipliersOfShareHolders = new uint256[]( - numOfShareHolders - ); - - uint256 shareHolderIndex = 0; - - for (uint256 i = 0; i < _splitsInfo.length; i++) { - SplitsInfo memory _splitInfo = _splitsInfo[i]; - uint256 roleMultiplier = _splitInfo.multiplierTop / - _splitInfo.multiplierBottom; - for (uint256 si = 0; si < _splitInfo.wearers.length; si++) { - address wearer = _splitInfo.wearers[si]; - - require( - HATS().balanceOf(wearer, _splitInfo.hatId) > 0, - "Invalid wearer" - ); - - uint256 tokenId = FRACTION_TOKEN().getTokenId( - _splitInfo.hatId, - wearer - ); - uint256 hatsTimeFrameMultiplier = _getHatsTimeFrameMultiplier( - wearer, - _splitInfo.hatId - ); - - // Get the recipients from FractionToken - address[] memory recipients = FRACTION_TOKEN() - .getTokenRecipients(tokenId); - for (uint256 j = 0; j < recipients.length; j++) { - shareHolders[shareHolderIndex] = recipients[j]; - wearers[shareHolderIndex] = wearer; - hatIdsOfShareHolders[shareHolderIndex] = _splitInfo.hatId; - roleMultipliersOfShareHolders[ - shareHolderIndex - ] = roleMultiplier; - hatsTimeFrameMultipliersOfShareHolders[ - shareHolderIndex - ] = hatsTimeFrameMultiplier; - shareHolderIndex++; - } - } - } - - uint256[] memory balanceOfShareHolders = FRACTION_TOKEN() - .balanceOfBatch(shareHolders, wearers, hatIdsOfShareHolders); - - totalAllocation = 0; - allocations = new uint256[](shareHolderIndex); - for (uint256 i = 0; i < shareHolderIndex; i++) { - uint256 share = balanceOfShareHolders[i] * - roleMultipliersOfShareHolders[i] * - hatsTimeFrameMultipliersOfShareHolders[i]; - totalAllocation += share; - allocations[i] = share; - } - - return (shareHolders, allocations, totalAllocation); - } - - function _getHatsTimeFrameMultiplier( - address _wearer, - uint256 _hatId - ) internal view returns (uint256) { - if (address(HATS_TIME_FRAME_MODULE()) == address(0)) return 1; - return - _sqrt( - HATS_TIME_FRAME_MODULE().getWearingElapsedTime(_wearer, _hatId) - ); - } - - function _sqrt(uint256 y) internal pure returns (uint256 z) { - if (y > 3) { - z = y; - uint256 x = y / 2 + 1; - while (x < z) { - z = x; - x = (y / x + x) / 2; - } - } else if (y != 0) { - z = 1; - } - // else z = 0 (default value) - } - - function _generateSalt( - SplitsInfo[] memory splitsInfo - ) internal pure returns (bytes32) { - return keccak256(abi.encode(splitsInfo)); - } + function HATS() public pure returns (IHats) { + return IHats(_getArgAddress(12)); + } + + function SPLIT_FACTORY_V2() public pure returns (ISplitFactoryV2) { + return ISplitFactoryV2(_getArgAddress(44)); + } + + function HATS_TIME_FRAME_MODULE() + public + pure + returns (IHatsTimeFrameModule) + { + return IHatsTimeFrameModule(_getArgAddress(76)); + } + + function FRACTION_TOKEN() public pure returns (IFractionToken) { + return IFractionToken(_getArgAddress(108)); + } + + /** + * @notice Creates a new split contract based on the provided splits information. + * @param _splitsInfo An array of SplitsInfo structs containing details about roles, wearers, and multipliers. + * @return The address of the newly created split contract. + */ + function create( + SplitsInfo[] memory _splitsInfo + ) external returns (address) { + ( + address[] memory shareHolders, + uint256[] memory allocations, + uint256 totalAllocation + ) = _calculateAllocations(_splitsInfo); + + SplitV2Lib.Split memory _splitParams = SplitV2Lib.Split({ + recipients: shareHolders, + allocations: allocations, + totalAllocation: totalAllocation, + distributionIncentive: 0 + }); + + address split = SPLIT_FACTORY_V2().createSplitDeterministic( + _splitParams, + address(this), + msg.sender, + _generateSalt(_splitsInfo) + ); + + emit SplitsCreated(split, shareHolders, allocations, totalAllocation); + + return split; + } + + /** + * @notice Previews the allocations without creating a split contract. + * @param _splitsInfo An array of SplitsInfo structs containing details about roles, wearers, and multipliers. + * @return shareHolders An array of shareholder addresses. + * @return percentages Corresponding allocation percentages (with 18 decimals) for each shareholder. + */ + function preview( + SplitsInfo[] memory _splitsInfo + ) + external + view + returns (address[] memory shareHolders, uint256[] memory percentages) + { + ( + address[] memory _shareHolders, + uint256[] memory allocations, + uint256 totalAllocation + ) = _calculateAllocations(_splitsInfo); + + percentages = new uint256[](allocations.length); + for (uint256 i = 0; i < allocations.length; i++) { + percentages[i] = (allocations[i] * 1e18) / totalAllocation; + } + + return (_shareHolders, percentages); + } + + /** + * @dev Internal function to calculate allocations for shareholders. + * @param _splitsInfo An array of SplitsInfo structs containing details about roles, wearers, and multipliers. + * @return shareHolders An array of shareholder addresses. + * @return allocations Corresponding allocations for each shareholder. + * @return totalAllocation Sum of all allocations. + */ + function _calculateAllocations( + SplitsInfo[] memory _splitsInfo + ) + internal + view + returns ( + address[] memory shareHolders, + uint256[] memory allocations, + uint256 totalAllocation + ) + { + uint256 numOfShareHolders = 0; + for (uint256 i = 0; i < _splitsInfo.length; i++) { + SplitsInfo memory _splitInfo = _splitsInfo[i]; + for (uint256 si = 0; si < _splitInfo.wearers.length; si++) { + uint256 tokenId = FRACTION_TOKEN().getTokenId( + _splitInfo.hatId, + _splitInfo.wearers[si] + ); + address[] memory recipients = FRACTION_TOKEN() + .getTokenRecipients(tokenId); + numOfShareHolders += recipients.length; + } + } + + shareHolders = new address[](numOfShareHolders); + address[] memory wearers = new address[](numOfShareHolders); + uint256[] memory hatIdsOfShareHolders = new uint256[]( + numOfShareHolders + ); + uint256[] memory roleMultipliersOfShareHolders = new uint256[]( + numOfShareHolders + ); + uint256[] memory hatsTimeFrameMultipliersOfShareHolders = new uint256[]( + numOfShareHolders + ); + + uint256 shareHolderIndex = 0; + + for (uint256 i = 0; i < _splitsInfo.length; i++) { + SplitsInfo memory _splitInfo = _splitsInfo[i]; + uint256 roleMultiplier = _splitInfo.multiplierTop / + _splitInfo.multiplierBottom; + for (uint256 si = 0; si < _splitInfo.wearers.length; si++) { + address wearer = _splitInfo.wearers[si]; + + require( + HATS().balanceOf(wearer, _splitInfo.hatId) > 0, + "Invalid wearer" + ); + + uint256 tokenId = FRACTION_TOKEN().getTokenId( + _splitInfo.hatId, + wearer + ); + uint256 hatsTimeFrameMultiplier = _getHatsTimeFrameMultiplier( + wearer, + _splitInfo.hatId + ); + + // Get the recipients from FractionToken + address[] memory recipients = FRACTION_TOKEN() + .getTokenRecipients(tokenId); + for (uint256 j = 0; j < recipients.length; j++) { + shareHolders[shareHolderIndex] = recipients[j]; + wearers[shareHolderIndex] = wearer; + hatIdsOfShareHolders[shareHolderIndex] = _splitInfo.hatId; + roleMultipliersOfShareHolders[ + shareHolderIndex + ] = roleMultiplier; + hatsTimeFrameMultipliersOfShareHolders[ + shareHolderIndex + ] = hatsTimeFrameMultiplier; + shareHolderIndex++; + } + } + } + + uint256[] memory balanceOfShareHolders = FRACTION_TOKEN() + .balanceOfBatch(shareHolders, wearers, hatIdsOfShareHolders); + + totalAllocation = 0; + allocations = new uint256[](shareHolderIndex); + for (uint256 i = 0; i < shareHolderIndex; i++) { + uint256 share = balanceOfShareHolders[i] * + roleMultipliersOfShareHolders[i] * + hatsTimeFrameMultipliersOfShareHolders[i]; + totalAllocation += share; + allocations[i] = share; + } + + return (shareHolders, allocations, totalAllocation); + } + + function _getHatsTimeFrameMultiplier( + address _wearer, + uint256 _hatId + ) internal view returns (uint256) { + if (address(HATS_TIME_FRAME_MODULE()) == address(0)) return 1; + return + _sqrt( + HATS_TIME_FRAME_MODULE().getWearingElapsedTime(_wearer, _hatId) + ); + } + + function _sqrt(uint256 y) internal pure returns (uint256 z) { + if (y > 3) { + z = y; + uint256 x = y / 2 + 1; + while (x < z) { + z = x; + x = (y / x + x) / 2; + } + } else if (y != 0) { + z = 1; + } + // else z = 0 (default value) + } + + function _generateSalt( + SplitsInfo[] memory splitsInfo + ) internal pure returns (bytes32) { + return keccak256(abi.encode(splitsInfo)); + } } diff --git a/pkgs/contract/contracts/splitscreator/SplitsCreatorFactory.sol b/pkgs/contract/contracts/splitscreator/SplitsCreatorFactory.sol index cd246f0..7848d42 100644 --- a/pkgs/contract/contracts/splitscreator/SplitsCreatorFactory.sol +++ b/pkgs/contract/contracts/splitscreator/SplitsCreatorFactory.sol @@ -5,14 +5,13 @@ pragma solidity ^0.8.24; import { LibClone } from "solady/src/utils/LibClone.sol"; import { SplitsCreator } from "./SplitsCreator.sol"; import { ISplitsCreator } from "./ISplitsCreator.sol"; -import { ERC2771ContextUpgradeable } from "./../ERC2771ContextUpgradeable.sol"; +import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; -contract SplitsCreatorFactory is ERC2771ContextUpgradeable { +contract SplitsCreatorFactory is Initializable { event SplitCreatorCreated( address indexed creator, address indexed splitCreator, uint256 topHatId, - address trustedForwarder, address splitFactoryV2, address hatsTimeFrameModule, address fractionToken @@ -21,16 +20,13 @@ contract SplitsCreatorFactory is ERC2771ContextUpgradeable { address public SPLITS_CREATOR_IMPLEMENTATION; function initialize( - address _trustedForwarderAddress, address _splitsCreatorImplementation ) public initializer { - __ERC2771Context_init(_trustedForwarderAddress); SPLITS_CREATOR_IMPLEMENTATION = _splitsCreatorImplementation; } function createSplitCreatorDeterministic( uint256 _topHatId, - address _trustedForwarder, address _hats, address _splitFactoryV2, address _hatsTimeFrameModule, @@ -40,7 +36,6 @@ contract SplitsCreatorFactory is ERC2771ContextUpgradeable { splitCreator = LibClone.cloneDeterministic( SPLITS_CREATOR_IMPLEMENTATION, abi.encode( - _trustedForwarder, _hats, _splitFactoryV2, _hatsTimeFrameModule, @@ -48,7 +43,6 @@ contract SplitsCreatorFactory is ERC2771ContextUpgradeable { ), _getSalt( _topHatId, - _trustedForwarder, _hats, _splitFactoryV2, _hatsTimeFrameModule, @@ -58,10 +52,9 @@ contract SplitsCreatorFactory is ERC2771ContextUpgradeable { ); emit SplitCreatorCreated( - _msgSender(), + msg.sender, splitCreator, _topHatId, - _trustedForwarder, _splitFactoryV2, _hatsTimeFrameModule, _fractionToken @@ -70,7 +63,6 @@ contract SplitsCreatorFactory is ERC2771ContextUpgradeable { function predictDeterministicAddress( uint256 _topHatId, - address _trustedForwarder, address _hats, address _splitFactoryV2, address _hatsTimeFrameModule, @@ -81,7 +73,6 @@ contract SplitsCreatorFactory is ERC2771ContextUpgradeable { LibClone.predictDeterministicAddress( SPLITS_CREATOR_IMPLEMENTATION, abi.encode( - _trustedForwarder, _hats, _splitFactoryV2, _hatsTimeFrameModule, @@ -89,7 +80,6 @@ contract SplitsCreatorFactory is ERC2771ContextUpgradeable { ), _getSalt( _topHatId, - _trustedForwarder, _hats, _splitFactoryV2, _hatsTimeFrameModule, @@ -102,7 +92,6 @@ contract SplitsCreatorFactory is ERC2771ContextUpgradeable { function _getSalt( uint256 _topHatId, - address _trustedForwarder, address _hats, address _splitFactoryV2, address _hatsTimeFrameModule, @@ -113,7 +102,6 @@ contract SplitsCreatorFactory is ERC2771ContextUpgradeable { keccak256( abi.encodePacked( _topHatId, - _trustedForwarder, _hats, _splitFactoryV2, _hatsTimeFrameModule, @@ -122,22 +110,4 @@ contract SplitsCreatorFactory is ERC2771ContextUpgradeable { ) ); } - - function _msgSender() - internal - view - override(ERC2771ContextUpgradeable) - returns (address sender) - { - return super._msgSender(); - } - - function _msgData() - internal - view - override(ERC2771ContextUpgradeable) - returns (bytes calldata) - { - return super._msgData(); - } } diff --git a/pkgs/contract/contracts/timeframe/HatsTimeFrameModule.sol b/pkgs/contract/contracts/timeframe/HatsTimeFrameModule.sol index ff1809d..17051c7 100644 --- a/pkgs/contract/contracts/timeframe/HatsTimeFrameModule.sol +++ b/pkgs/contract/contracts/timeframe/HatsTimeFrameModule.sol @@ -3,13 +3,8 @@ pragma solidity ^0.8.24; import { IHatsTimeFrameModule } from "./IHatsTimeFrameModule.sol"; import { HatsModule } from "../hats/module/HatsModule.sol"; -import { ERC2771Context } from "@openzeppelin/contracts/metatx/ERC2771Context.sol"; -contract HatsTimeFrameModule is - ERC2771Context, - HatsModule, - IHatsTimeFrameModule -{ +contract HatsTimeFrameModule is HatsModule, IHatsTimeFrameModule { // hatId => wearer => wore timestamp mapping(uint256 => mapping(address => uint256)) public woreTime; @@ -24,15 +19,18 @@ contract HatsTimeFrameModule is /** * @dev Constructor to initialize the trusted forwarder. - * @param _trustedForwarder Address of the trusted forwarder contract. + * @param _version The version of the contract. */ - constructor( - address _trustedForwarder, - string memory _version - ) ERC2771Context(_trustedForwarder) HatsModule(_version) {} + constructor(string memory _version) HatsModule(_version) {} - function mintHat(uint256 hatId, address wearer) external { - _setWoreTime(wearer, hatId); + /** + * @dev Mint a hat for a specific address. + * @param hatId The ID of the hat that was minted. + * @param wearer The address of the person who received the hat. + * @param time The specific timestamp when the hat was minted. + */ + function mintHat(uint256 hatId, address wearer, uint256 time) external { + _setWoreTime(wearer, hatId, time); isActive[hatId][wearer] = true; HATS().mintHat(hatId, wearer); } @@ -70,9 +68,13 @@ contract HatsTimeFrameModule is * Can only be called by the contract that handles the minting logic. * @param hatId The ID of the hat that was minted. */ - function _setWoreTime(address wearer, uint256 hatId) internal { + function _setWoreTime( + address wearer, + uint256 hatId, + uint256 time + ) internal { require(woreTime[hatId][wearer] == 0, "Hat already minted"); - woreTime[hatId][wearer] = block.timestamp; + woreTime[hatId][wearer] = time == 0 ? block.timestamp : time; } /** @@ -108,30 +110,4 @@ contract HatsTimeFrameModule is return activeTime; } - - /** - * @dev Override _msgSender to use the context from ERC2771Context. - * @return The message sender address. - */ - function _msgSender() - internal - view - override(ERC2771Context) - returns (address) - { - return ERC2771Context._msgSender(); - } - - /** - * @dev Override _msgData to use the context from ERC2771Context. - * @return The calldata of the message. - */ - function _msgData() - internal - view - override(ERC2771Context) - returns (bytes calldata) - { - return ERC2771Context._msgData(); - } } diff --git a/pkgs/contract/helpers/deploy/BigBang.ts b/pkgs/contract/helpers/deploy/BigBang.ts index 30fcd9d..994afa0 100644 --- a/pkgs/contract/helpers/deploy/BigBang.ts +++ b/pkgs/contract/helpers/deploy/BigBang.ts @@ -4,7 +4,6 @@ import { Address } from "viem"; export type BigBang = Awaited>["BigBang"]; export const deployBigBang = async (params: { - trustedForwarder: Address; hatsContractAddress: Address; hatsModuleFacotryAddress: Address; hatsTimeFrameModule_impl: Address; @@ -28,7 +27,6 @@ export const deployBigBang = async (params: { const _BigBang = await upgrades.deployProxy( bigBang, [ - params.trustedForwarder, params.hatsContractAddress, params.hatsModuleFacotryAddress, params.hatsTimeFrameModule_impl, diff --git a/pkgs/contract/helpers/deploy/FractionToken.ts b/pkgs/contract/helpers/deploy/FractionToken.ts index 35f55af..b3141ed 100644 --- a/pkgs/contract/helpers/deploy/FractionToken.ts +++ b/pkgs/contract/helpers/deploy/FractionToken.ts @@ -8,13 +8,12 @@ export type FractionToken = Awaited< export const deployFractionToken = async ( uri: string, tokenSupply: bigint = 10000n, - hatsContractAddress: Address, - forwarderAddress: Address + hatsContractAddress: Address ) => { const fractionToken = await ethers.getContractFactory("FractionToken"); const _FractionToken = await upgrades.deployProxy( fractionToken, - [uri, tokenSupply, hatsContractAddress, forwarderAddress], + [uri, tokenSupply, hatsContractAddress], { initializer: "initialize", } diff --git a/pkgs/contract/helpers/deploy/Hats.ts b/pkgs/contract/helpers/deploy/Hats.ts index 31f5bd4..773d687 100644 --- a/pkgs/contract/helpers/deploy/Hats.ts +++ b/pkgs/contract/helpers/deploy/Hats.ts @@ -36,12 +36,8 @@ export const deployEmptyHatsModule = async () => { return { HatsModule }; }; -export const deployHatsTimeFrameModule = async ( - forwarderAddress: Address = zeroAddress, - version: string = "0.0.0" -) => { +export const deployHatsTimeFrameModule = async (version: string = "0.0.0") => { const HatsTimeFrameModule = await viem.deployContract("HatsTimeFrameModule", [ - forwarderAddress, version, ]); diff --git a/pkgs/contract/helpers/deploy/Splits.ts b/pkgs/contract/helpers/deploy/Splits.ts index 43c564e..94762b0 100644 --- a/pkgs/contract/helpers/deploy/Splits.ts +++ b/pkgs/contract/helpers/deploy/Splits.ts @@ -43,17 +43,15 @@ export const deploySplitsProtocol = async () => { }; export const deploySplitsCreatorFactory = async ( - forwarderAddress: Address, splitsCreatorImpl: Address ) => { - const splitsCreatorFactory = await ethers.getContractFactory("SplitsCreatorFactory"); + const splitsCreatorFactory = await ethers.getContractFactory( + "SplitsCreatorFactory" + ); const _SplitsCreatorFactory = await upgrades.deployProxy( splitsCreatorFactory, - [ - forwarderAddress, - splitsCreatorImpl - ], + [splitsCreatorImpl], { initializer: "initialize", } diff --git a/pkgs/contract/helpers/upgrade/bigbang.ts b/pkgs/contract/helpers/upgrade/bigbang.ts index 16cd3b9..d81586f 100644 --- a/pkgs/contract/helpers/upgrade/bigbang.ts +++ b/pkgs/contract/helpers/upgrade/bigbang.ts @@ -10,8 +10,7 @@ import { Address } from "viem"; */ export const upgradeBigBang = async ( contractAddress: string, - contractName: string, - params?: any[] + contractName: string ) => { // 新しいコントラクトのファクトリーを取得 const BigBang_Mock_v2 = await ethers.getContractFactory(contractName); diff --git a/pkgs/contract/test/BigBang.ts b/pkgs/contract/test/BigBang.ts index dc30b5d..eb254c9 100644 --- a/pkgs/contract/test/BigBang.ts +++ b/pkgs/contract/test/BigBang.ts @@ -67,8 +67,7 @@ describe("BigBang", () => { const { FractionToken: _FractionToken } = await deployFractionToken( "", 10000n, - Hats.address, - zeroAddress + Hats.address ); FractionToken = _FractionToken; @@ -76,7 +75,7 @@ describe("BigBang", () => { SplitsCreator_IMPL = _SplitsCreator; const { SplitsCreatorFactory: _SplitsCreatorFactory } = - await deploySplitsCreatorFactory(zeroAddress, SplitsCreator_IMPL.address); + await deploySplitsCreatorFactory(SplitsCreator_IMPL.address); SplitsCreatorFactory = _SplitsCreatorFactory; @@ -86,7 +85,6 @@ describe("BigBang", () => { it("should deploy BigBang", async () => { const { BigBang: _BigBang } = await deployBigBang({ - trustedForwarder: zeroAddress, hatsContractAddress: Hats.address, hatsModuleFacotryAddress: HatsModuleFactory.address, hatsTimeFrameModule_impl: HatsTimeFrameModule_IMPL.address, @@ -112,7 +110,6 @@ describe("BigBang", () => { "tophatURI", "hatterhatDetails", "hatterhatURI", - relayer.account?.address!, ], { account: address1.account } ); @@ -304,8 +301,7 @@ describe("BigBang", () => { // BigBangをアップグレード const newBigBang = await upgradeBigBang( BigBang.address, - "BigBang_Mock_v2", - ["", 10000n, Hats.address, zeroAddress] + "BigBang_Mock_v2" ); // upgrade後にしかないメソッドを実行 @@ -317,8 +313,7 @@ describe("BigBang", () => { // BigBangをアップグレード const newBigBang = await upgradeBigBang( BigBang.address, - "BigBang_Mock_v2", - ["", 10000n, Hats.address, zeroAddress] + "BigBang_Mock_v2" ); const txHash = await newBigBang.write.bigbang( @@ -328,7 +323,6 @@ describe("BigBang", () => { "tophatURI", "hatterhatDetails", "hatterhatURI", - address1.account?.address!, ], { account: address1.account } ); diff --git a/pkgs/contract/test/FractionToken.ts b/pkgs/contract/test/FractionToken.ts index 7ae5197..066d263 100644 --- a/pkgs/contract/test/FractionToken.ts +++ b/pkgs/contract/test/FractionToken.ts @@ -31,8 +31,7 @@ describe("FractionToken", () => { const { FractionToken: _FractionToken } = await deployFractionToken( "", 10000n, - Hats.address, - zeroAddress + Hats.address ); FractionToken = _FractionToken; @@ -57,7 +56,8 @@ describe("FractionToken", () => { data: log.data, topics: log.topics, }); - if (decodedLog.eventName === "HatCreated") topHatId = decodedLog.args.id; + if (decodedLog.eventName === "HatCreated") + topHatId = decodedLog.args.id; } catch (error) {} } @@ -132,10 +132,9 @@ describe("FractionToken", () => { expect(balance).to.equal(0n); // address3が自分自身にtokenを追加でmint - await FractionToken.write.mint( - [hatId, address3.account?.address!, 5000n], - { account: address3.account! } - ); + await FractionToken.write.mint([hatId, address3.account?.address!, 5000n], { + account: address3.account!, + }); const tokenId = await FractionToken.read.getTokenId([ hatId, @@ -156,12 +155,7 @@ describe("FractionToken", () => { // address2のtokenをaddress1が半分burnする await FractionToken.write.burn( - [ - address2.account?.address!, - address2.account?.address!, - hatId, - 2500n - ], + [address2.account?.address!, address2.account?.address!, hatId, 2500n], { account: address1.account! } ); @@ -193,22 +187,22 @@ describe("FractionToken", () => { it("should fail to mint a token", async () => { // roleのない人にtokenはmintできない await FractionToken.write - .mintInitialSupply( - [hatId, address4.account?.address!], - { account: address1.account! } - ) + .mintInitialSupply([hatId, address4.account?.address!], { + account: address1.account!, + }) .catch((error: any) => { expect(error.message).to.include("This account does not have the role"); }); // 権限のない人はtokenをmintできない await FractionToken.write - .mintInitialSupply( - [hatId, address2.account?.address!], - { account: address2.account! } - ) + .mintInitialSupply([hatId, address2.account?.address!], { + account: address2.account!, + }) .catch((error: any) => { - expect(error.message).to.include("This msg.sender does not have the authority"); + expect(error.message).to.include( + "This msg.sender does not have the authority" + ); }); // tokenは二度mintできない @@ -220,22 +214,24 @@ describe("FractionToken", () => { // initial supplyを受けていない場合は追加のmintはできない await FractionToken.write - .mint( - [hatId, address4.account?.address!, 5000n], - { account: address4.account! } - ) + .mint([hatId, address4.account?.address!, 5000n], { + account: address4.account!, + }) .catch((error: any) => { - expect(error.message).to.include("This account has not received the initial supply"); + expect(error.message).to.include( + "This account has not received the initial supply" + ); }); // tokenの最初の受け取り手以外は追加でmintできない await FractionToken.write - .mint( - [hatId, address2.account?.address!, 5000n], - { account: address4.account! } - ) + .mint([hatId, address2.account?.address!, 5000n], { + account: address4.account!, + }) .catch((error: any) => { - expect(error.message).to.include("Only the first recipient can additionally mint"); + expect(error.message).to.include( + "Only the first recipient can additionally mint" + ); }); }); @@ -243,12 +239,7 @@ describe("FractionToken", () => { // address2のtokenはaddress3によってburnできない await FractionToken.write .burn( - [ - address2.account?.address!, - address2.account?.address!, - hatId, - 5000n, - ], + [address2.account?.address!, address2.account?.address!, hatId, 5000n], { account: address3.account! } ) .catch((error: any) => { @@ -332,7 +323,7 @@ describe("FractionToken", () => { address2.account?.address!, hatId, ]); - + expect(balance as bigint).to.equal(6250n); }); @@ -346,20 +337,20 @@ describe("FractionToken", () => { // 権限のない人にtokenはmintできない await newFractionToken.write - .mintInitialSupply( - [hatId, address4.account?.address!], - { account: address1.account! } - ) + .mintInitialSupply([hatId, address4.account?.address!], { + account: address1.account!, + }) .catch((error: any) => { - expect(error.message).to.include("This account does not have the role"); + expect(error.message).to.include( + "This account does not have the role" + ); }); // tokenは二度mintできない await newFractionToken.write - .mintInitialSupply( - [hatId, address2.account?.address!], - { account: address1.account! } - ) + .mintInitialSupply([hatId, address2.account?.address!], { + account: address1.account!, + }) .catch((error: any) => { expect(error.message).to.include("This account has already received"); }); diff --git a/pkgs/contract/test/HatsTimeFrameModule.ts b/pkgs/contract/test/HatsTimeFrameModule.ts index 86096e5..dcf283f 100644 --- a/pkgs/contract/test/HatsTimeFrameModule.ts +++ b/pkgs/contract/test/HatsTimeFrameModule.ts @@ -21,6 +21,7 @@ describe("HatsTimeFrameModule", () => { let address2: WalletClient; let topHatId: bigint; + let roleHatId!: bigint; let publicClient: PublicClient; @@ -121,8 +122,6 @@ describe("HatsTimeFrameModule", () => { hash: txHash, }); - let roleHatId!: bigint; - for (const log of receipt.logs) { const decodedLog = decodeEventLog({ abi: Hats.abi, @@ -133,19 +132,22 @@ describe("HatsTimeFrameModule", () => { roleHatId = decodedLog.args.id; } } + }); + it("mint hat", async () => { const initialTime = BigInt(await time.latest()); await HatsTimeFrameModule.write.mintHat([ - roleHatId, - address1.account?.address!, + roleHatId, + address1.account?.address!, + 0n, ]); const afterMintTime = BigInt(await time.latest()); let woreTime = await HatsTimeFrameModule.read.getWoreTime([ - address1.account?.address!, - roleHatId, + address1.account?.address!, + roleHatId, ]); expect(woreTime).to.equal(afterMintTime); @@ -211,7 +213,8 @@ describe("HatsTimeFrameModule", () => { const currentTime3 = BigInt(await time.latest()); - expectedElapsedTime = totalActiveTimeAfterDeactivation + (currentTime3 - woreTime); + expectedElapsedTime = + totalActiveTimeAfterDeactivation + (currentTime3 - woreTime); elapsedTime = await HatsTimeFrameModule.read.getWearingElapsedTime([ address1.account?.address!, @@ -220,4 +223,22 @@ describe("HatsTimeFrameModule", () => { expect(elapsedTime).to.equal(expectedElapsedTime); }); -}); \ No newline at end of file + + it("mint hat previous time", async () => { + const initialTime = BigInt(await time.latest()); + await time.increaseTo(initialTime + 10000n); + + await HatsTimeFrameModule.write.mintHat([ + roleHatId, + address2.account?.address!, + initialTime + 5000n, + ]); + + const woreTime = await HatsTimeFrameModule.read.getWoreTime([ + address2.account?.address!, + roleHatId, + ]); + + expect(woreTime).to.equal(initialTime + 5000n); + }); +}); diff --git a/pkgs/contract/test/IntegrationTest.ts b/pkgs/contract/test/IntegrationTest.ts index 0aeae14..e223282 100644 --- a/pkgs/contract/test/IntegrationTest.ts +++ b/pkgs/contract/test/IntegrationTest.ts @@ -90,7 +90,6 @@ describe("IntegrationTest", () => { "", 10000n, Hats.address, - zeroAddress ); FractionToken = _FractionToken; @@ -98,7 +97,7 @@ describe("IntegrationTest", () => { SplitsCreator_IMPL = _SplitsCreator; const { SplitsCreatorFactory: _SplitsCreatorFactory } = - await deploySplitsCreatorFactory(zeroAddress, SplitsCreator_IMPL.address); + await deploySplitsCreatorFactory(SplitsCreator_IMPL.address); SplitsCreatorFactory = _SplitsCreatorFactory; @@ -109,7 +108,6 @@ describe("IntegrationTest", () => { it("should deploy BigBang", async () => { const { BigBang: _BigBang } = await deployBigBang({ - trustedForwarder: zeroAddress, hatsContractAddress: Hats.address, hatsModuleFacotryAddress: HatsModuleFactory.address, hatsTimeFrameModule_impl: HatsTimeFrameModule_IMPL.address, @@ -131,7 +129,6 @@ describe("IntegrationTest", () => { "tophatURI", "hatterhatDetails", "hatterhatURI", - deployer.account?.address!, ], { account: deployer.account } ); @@ -217,6 +214,7 @@ describe("IntegrationTest", () => { await HatsTimeFrameModuleByBigBang.write.mintHat([ hat1_id, address1.account?.address!, + 0n, ]); expect( @@ -226,6 +224,7 @@ describe("IntegrationTest", () => { await HatsTimeFrameModuleByBigBang.write.mintHat([ hat1_id, address2.account?.address!, + 0n, ]); expect( @@ -235,8 +234,14 @@ describe("IntegrationTest", () => { it("should mint FractionToken", async () => { // address1,address2にtokenをmint - await FractionToken.write.mintInitialSupply([hat1_id, address1.account?.address!]); - await FractionToken.write.mintInitialSupply([hat1_id, address2.account?.address!]); + await FractionToken.write.mintInitialSupply([ + hat1_id, + address1.account?.address!, + ]); + await FractionToken.write.mintInitialSupply([ + hat1_id, + address2.account?.address!, + ]); // Check balance for address1 let balance1 = await FractionToken.read.balanceOf([ diff --git a/pkgs/contract/test/SplitsCreator.ts b/pkgs/contract/test/SplitsCreator.ts index 710f74d..f683ca8 100644 --- a/pkgs/contract/test/SplitsCreator.ts +++ b/pkgs/contract/test/SplitsCreator.ts @@ -76,8 +76,7 @@ describe("SplitsCreator Factory", () => { const { FractionToken: _FractionToken } = await deployFractionToken( "", 10000n, - Hats.address, - zeroAddress + Hats.address ); FractionToken = _FractionToken; @@ -120,7 +119,7 @@ describe("SplitsCreator Factory", () => { it("Should deploy SplitsCreatorFactory", async () => { const { SplitsCreatorFactory: _SplitsCreatorFactory } = - await deploySplitsCreatorFactory(zeroAddress, SplitsCreator_IMPL.address); + await deploySplitsCreatorFactory(SplitsCreator_IMPL.address); SplitsCreatorFactory = _SplitsCreatorFactory; @@ -128,7 +127,7 @@ describe("SplitsCreator Factory", () => { expect( await SplitsCreatorFactory.read.predictDeterministicAddress([ topHatId, - zeroAddress, + Hats.address, PullSplitsFactory.address, HatsTimeFrameModule.address, @@ -142,7 +141,6 @@ describe("SplitsCreator Factory", () => { const predictedAddress = await SplitsCreatorFactory.read.predictDeterministicAddress([ topHatId, - address1.account?.address!, Hats.address, PullSplitsFactory.address, HatsTimeFrameModule.address, @@ -152,7 +150,6 @@ describe("SplitsCreator Factory", () => { await SplitsCreatorFactory.write.createSplitCreatorDeterministic([ topHatId, - address1.account?.address!, Hats.address, PullSplitsFactory.address, HatsTimeFrameModule.address, @@ -225,8 +222,7 @@ describe("CreateSplit", () => { const { FractionToken: _FractionToken } = await deployFractionToken( "", 10000n, - Hats.address, - zeroAddress + Hats.address ); FractionToken = _FractionToken; @@ -269,14 +265,13 @@ describe("CreateSplit", () => { ); const { SplitsCreatorFactory: _SplitsCreatorFactory } = - await deploySplitsCreatorFactory(zeroAddress, SplitsCreator_IMPL.address); + await deploySplitsCreatorFactory(SplitsCreator_IMPL.address); SplitsCreatorFactory = _SplitsCreatorFactory; let txHash = await SplitsCreatorFactory.write.createSplitCreatorDeterministic([ topHatId, - address1.account?.address!, Hats.address, PullSplitsFactory.address, HatsTimeFrameModule.address, @@ -385,6 +380,7 @@ describe("CreateSplit", () => { await HatsTimeFrameModule.write.mintHat([ hat1_id, address1.account?.address!, + 0n, ]); address1WoreTime = await publicClient @@ -398,6 +394,7 @@ describe("CreateSplit", () => { await HatsTimeFrameModule.write.mintHat([ hat1_id, address2.account?.address!, + 0n, ]); address2WoreTime = await publicClient @@ -409,6 +406,7 @@ describe("CreateSplit", () => { await HatsTimeFrameModule.write.mintHat([ hat2_id, address3.account?.address!, + 0n, ]); address3WoreTime = await publicClient From 5869007f15c21f667cfb60f44423990c49d34d3d Mon Sep 17 00:00:00 2001 From: yu23ki14 Date: Mon, 9 Dec 2024 22:13:53 +0900 Subject: [PATCH 2/2] fix deploy script --- pkgs/contract/.openzeppelin/sepolia.json | 398 +++++++++++++++++++ pkgs/contract/outputs/contracts-sepolia.json | 10 +- pkgs/contract/scripts/deploy/all.ts | 4 +- 3 files changed, 404 insertions(+), 8 deletions(-) diff --git a/pkgs/contract/.openzeppelin/sepolia.json b/pkgs/contract/.openzeppelin/sepolia.json index 663bc41..3da8ea8 100644 --- a/pkgs/contract/.openzeppelin/sepolia.json +++ b/pkgs/contract/.openzeppelin/sepolia.json @@ -10,6 +10,21 @@ "address": "0x08EA1AFcF193b19EcEd95538AcCDA4D770eeC147", "txHash": "0x8eef64bbc8e38b4543da5f873ad325f83628fae3cfea00452f740cd1eccfa5f8", "kind": "transparent" + }, + { + "address": "0xd921517fdF141d97C289bDb9686f51A1375dCc69", + "txHash": "0x66972a35a2daff39ec5f5280361cfb9016ce53b19e5730310c9a033d71e4b634", + "kind": "transparent" + }, + { + "address": "0xbe985Fdd213d85d72C82cf34774C5D830e806FcB", + "txHash": "0xd28cccaf12be77f3503c8e663699b89b157872299a2f153c8c5bbea55b565bcd", + "kind": "transparent" + }, + { + "address": "0x08B4c53b98f46B14E2AD00189C2Aa3b9F3d0c8f3", + "txHash": "0x0b7d0cacd542bf718e6d99c13f12690b07a0f3228c31d013a2aa399cb67ae04e", + "kind": "transparent" } ], "impls": { @@ -684,6 +699,389 @@ ] } } + }, + "a50d3370e9a1f0391a140cda5e767c98982881d6b86245dea5f89ba08e4f5493": { + "address": "0xCe060E28bb926d914583972fda686694e6703Cf4", + "txHash": "0x13369a16af7294d59e33b95630e8c28ddac8bf56df06b06ef410e3388396be72", + "layout": { + "solcVersion": "0.8.24", + "storage": [ + { + "label": "TOKEN_SUPPLY", + "offset": 0, + "slot": "0", + "type": "t_uint256", + "contract": "FractionToken", + "src": "contracts/fractiontoken/FractionToken.sol:8" + }, + { + "label": "tokenRecipients", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_uint256,t_array(t_address)dyn_storage)", + "contract": "FractionToken", + "src": "contracts/fractiontoken/FractionToken.sol:10" + }, + { + "label": "hatsContract", + "offset": 0, + "slot": "2", + "type": "t_contract(IHats)16981", + "contract": "FractionToken", + "src": "contracts/fractiontoken/FractionToken.sol:12" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_mapping(t_address,t_bool))": { + "label": "mapping(address => mapping(address => bool))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { + "label": "mapping(uint256 => mapping(address => uint256))", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(ERC1155Storage)166_storage": { + "label": "struct ERC1155Upgradeable.ERC1155Storage", + "members": [ + { + "label": "_balances", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))", + "offset": 0, + "slot": "0" + }, + { + "label": "_operatorApprovals", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))", + "offset": 0, + "slot": "1" + }, + { + "label": "_uri", + "type": "t_string_storage", + "offset": 0, + "slot": "2" + } + ], + "numberOfBytes": "96" + }, + "t_struct(InitializableStorage)73_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_array(t_address)dyn_storage": { + "label": "address[]", + "numberOfBytes": "32" + }, + "t_contract(IHats)16981": { + "label": "contract IHats", + "numberOfBytes": "20" + }, + "t_mapping(t_uint256,t_array(t_address)dyn_storage)": { + "label": "mapping(uint256 => address[])", + "numberOfBytes": "32" + } + }, + "namespaces": { + "erc7201:openzeppelin.storage.ERC1155": [ + { + "contract": "ERC1155Upgradeable", + "label": "_balances", + "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))", + "src": "@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol:27", + "offset": 0, + "slot": "0" + }, + { + "contract": "ERC1155Upgradeable", + "label": "_operatorApprovals", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))", + "src": "@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol:29", + "offset": 0, + "slot": "1" + }, + { + "contract": "ERC1155Upgradeable", + "label": "_uri", + "type": "t_string_storage", + "src": "@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol:32", + "offset": 0, + "slot": "2" + } + ], + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + } + }, + "44db4a69fff808b4e6acc9c9856b1d7b212464248b554fcc4f1508639eb93381": { + "address": "0xf3d9c56946Fa9E974b86e220645e563615D654Cc", + "txHash": "0x5227ef554354e74bad8b056ba94c62e0414e90cd773e90dcaf398c456f60802d", + "layout": { + "solcVersion": "0.8.24", + "storage": [ + { + "label": "SPLITS_CREATOR_IMPLEMENTATION", + "offset": 0, + "slot": "0", + "type": "t_address", + "contract": "SplitsCreatorFactory", + "src": "contracts/splitscreator/SplitsCreatorFactory.sol:20" + } + ], + "types": { + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_struct(InitializableStorage)7_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_address": { + "label": "address", + "numberOfBytes": "20" + } + }, + "namespaces": { + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + } + }, + "7840b8c8fb43a65c86b7b0642058baa343a8b6f483c8d9d2370e87beeb6c44ce": { + "address": "0x6AcF43dCe73D9EA7029180A4C51C7De80552B4d7", + "txHash": "0xc134fddba4992574c96b67408e24d8cc1b1b8a63529bd0b628e83c1aa26004ca", + "layout": { + "solcVersion": "0.8.24", + "storage": [ + { + "label": "Hats", + "offset": 0, + "slot": "0", + "type": "t_contract(IHats)16981", + "contract": "BigBang", + "src": "contracts/bigbang/BigBang.sol:11" + }, + { + "label": "HatsModuleFactory", + "offset": 0, + "slot": "1", + "type": "t_contract(IHatsModuleFactory)9741", + "contract": "BigBang", + "src": "contracts/bigbang/BigBang.sol:13" + }, + { + "label": "SplitsCreatorFactory", + "offset": 0, + "slot": "2", + "type": "t_contract(ISplitsCreatorFactory)21158", + "contract": "BigBang", + "src": "contracts/bigbang/BigBang.sol:15" + }, + { + "label": "HatsTimeFrameModule_IMPL", + "offset": 0, + "slot": "3", + "type": "t_address", + "contract": "BigBang", + "src": "contracts/bigbang/BigBang.sol:17" + }, + { + "label": "SplitsFactoryV2", + "offset": 0, + "slot": "4", + "type": "t_address", + "contract": "BigBang", + "src": "contracts/bigbang/BigBang.sol:19" + }, + { + "label": "FractionToken", + "offset": 0, + "slot": "5", + "type": "t_address", + "contract": "BigBang", + "src": "contracts/bigbang/BigBang.sol:21" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_struct(InitializableStorage)73_storage": { + "label": "struct Initializable.InitializableStorage", + "members": [ + { + "label": "_initialized", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "_initializing", + "type": "t_bool", + "offset": 8, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_struct(OwnableStorage)13_storage": { + "label": "struct OwnableUpgradeable.OwnableStorage", + "members": [ + { + "label": "_owner", + "type": "t_address", + "offset": 0, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_contract(IHats)16981": { + "label": "contract IHats", + "numberOfBytes": "20" + }, + "t_contract(IHatsModuleFactory)9741": { + "label": "contract IHatsModuleFactory", + "numberOfBytes": "20" + }, + "t_contract(ISplitsCreatorFactory)21158": { + "label": "contract ISplitsCreatorFactory", + "numberOfBytes": "20" + } + }, + "namespaces": { + "erc7201:openzeppelin.storage.Ownable": [ + { + "contract": "OwnableUpgradeable", + "label": "_owner", + "type": "t_address", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:24", + "offset": 0, + "slot": "0" + } + ], + "erc7201:openzeppelin.storage.Initializable": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint64", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:69", + "offset": 0, + "slot": "0" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:73", + "offset": 8, + "slot": "0" + } + ] + } + } } } } diff --git a/pkgs/contract/outputs/contracts-sepolia.json b/pkgs/contract/outputs/contracts-sepolia.json index a556fe7..95f38b0 100644 --- a/pkgs/contract/outputs/contracts-sepolia.json +++ b/pkgs/contract/outputs/contracts-sepolia.json @@ -3,10 +3,10 @@ "Hats": "0x3bc1A0Ad72417f2d411118085256fC53CBdDd137", "HatsModuleFactory": "0x0a3f85fa597B6a967271286aA0724811acDF5CD9", "PullSplitsFactory": "0x80f1B766817D04870f115fEBbcCADF8DBF75E017", - "BigBang": "0x08EA1AFcF193b19EcEd95538AcCDA4D770eeC147", - "FractionToken": "0x4747b535f1C4a48bbfc88CA68DC8973DD38Eb413", - "SplitsCreatorFactory": "0x96bbed9989387bb512ea29a8fa54f03d33bad169", - "SplitsCreator": "0x9c3648df4bb82fdf067a9b083900a986f9b27e9a", - "HatsTimeFrameModule": "0x8760411d317e560021db83b35971ab0dded4e205" + "BigBang": "0x08B4c53b98f46B14E2AD00189C2Aa3b9F3d0c8f3", + "FractionToken": "0xd921517fdF141d97C289bDb9686f51A1375dCc69", + "SplitsCreatorFactory": "0xbe985Fdd213d85d72C82cf34774C5D830e806FcB", + "SplitsCreator": "0x6b5d2e27ff74e9adf4d23aebb9efb52867823583", + "HatsTimeFrameModule": "0x9878f0905bcea0c2380be801f24dd5654f9b678f" } } \ No newline at end of file diff --git a/pkgs/contract/scripts/deploy/all.ts b/pkgs/contract/scripts/deploy/all.ts index 0f3fc7b..4a0addb 100644 --- a/pkgs/contract/scripts/deploy/all.ts +++ b/pkgs/contract/scripts/deploy/all.ts @@ -34,8 +34,7 @@ const deployAll = async () => { const { FractionToken } = await deployFractionToken( "", 10000n, - Hats as Address, - zeroAddress + Hats as Address ); const { SplitsCreator } = await deploySplitsCreator(); @@ -45,7 +44,6 @@ const deployAll = async () => { ); const { BigBang } = await deployBigBang({ - trustedForwarder: zeroAddress, hatsContractAddress: Hats as Address, hatsModuleFacotryAddress: HatsModuleFactory as Address, hatsTimeFrameModule_impl: HatsTimeFrameModule.address,