From afe6b432da15aa63899065187906451939844f9c Mon Sep 17 00:00:00 2001 From: Adam Gall Date: Thu, 12 Sep 2024 10:47:10 -0400 Subject: [PATCH] Merge pull request #101 from decentdao/streams-on-hats-tree-creation Streams on hats tree creation --- contracts/DecentHats_0_1_0.sol | 179 +++-- .../sablier/ISablierV2LockupLinear.sol | 11 + contracts/interfaces/sablier/LockupLinear.sol | 28 + contracts/{mock => mocks}/ERC6551Registry.sol | 0 contracts/{mock => mocks}/MockContract.sol | 0 contracts/mocks/MockERC20.sol | 12 + contracts/{mock => mocks}/MockERC721.sol | 0 contracts/{mock => mocks}/MockHats.sol | 0 contracts/{mock => mocks}/MockHatsAccount.sol | 0 contracts/mocks/MockSablierV2LockupLinear.sol | 159 +++++ .../{mock => mocks}/MockVotingStrategy.sol | 0 deployments/base/DecentHats_0_1_0.json | 180 ++++- .../512807b5d71481c693c202ae23158904.json | 59 ++ deployments/mainnet/DecentHats_0_1_0.json | 180 ++++- .../512807b5d71481c693c202ae23158904.json | 59 ++ deployments/optimism/DecentHats_0_1_0.json | 180 ++++- .../512807b5d71481c693c202ae23158904.json | 59 ++ deployments/polygon/DecentHats_0_1_0.json | 196 +++++- .../512807b5d71481c693c202ae23158904.json | 59 ++ deployments/sepolia/DecentHats_0_1_0.json | 180 ++++- .../512807b5d71481c693c202ae23158904.json | 59 ++ test/DecentHats.test.ts | 340 ---------- test/DecentHats_0_1_0.test.ts | 617 ++++++++++++++++++ 23 files changed, 2072 insertions(+), 485 deletions(-) create mode 100644 contracts/interfaces/sablier/ISablierV2LockupLinear.sol create mode 100644 contracts/interfaces/sablier/LockupLinear.sol rename contracts/{mock => mocks}/ERC6551Registry.sol (100%) rename contracts/{mock => mocks}/MockContract.sol (100%) create mode 100644 contracts/mocks/MockERC20.sol rename contracts/{mock => mocks}/MockERC721.sol (100%) rename contracts/{mock => mocks}/MockHats.sol (100%) rename contracts/{mock => mocks}/MockHatsAccount.sol (100%) create mode 100644 contracts/mocks/MockSablierV2LockupLinear.sol rename contracts/{mock => mocks}/MockVotingStrategy.sol (100%) create mode 100644 deployments/base/solcInputs/512807b5d71481c693c202ae23158904.json create mode 100644 deployments/mainnet/solcInputs/512807b5d71481c693c202ae23158904.json create mode 100644 deployments/optimism/solcInputs/512807b5d71481c693c202ae23158904.json create mode 100644 deployments/polygon/solcInputs/512807b5d71481c693c202ae23158904.json create mode 100644 deployments/sepolia/solcInputs/512807b5d71481c693c202ae23158904.json delete mode 100644 test/DecentHats.test.ts create mode 100644 test/DecentHats_0_1_0.test.ts diff --git a/contracts/DecentHats_0_1_0.sol b/contracts/DecentHats_0_1_0.sol index fc49ff04..c00dadaa 100644 --- a/contracts/DecentHats_0_1_0.sol +++ b/contracts/DecentHats_0_1_0.sol @@ -4,18 +4,33 @@ pragma solidity =0.8.19; import {Enum} from "@gnosis.pm/safe-contracts/contracts/common/Enum.sol"; import {IAvatar} from "@gnosis.pm/zodiac/contracts/interfaces/IAvatar.sol"; import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {IERC6551Registry} from "./interfaces/IERC6551Registry.sol"; import {IHats} from "./interfaces/hats/IHats.sol"; +import {ISablierV2LockupLinear} from "./interfaces/sablier/ISablierV2LockupLinear.sol"; +import {LockupLinear} from "./interfaces/sablier/LockupLinear.sol"; contract DecentHats_0_1_0 { string public constant NAME = "DecentHats_0_1_0"; + struct SablierStreamParams { + ISablierV2LockupLinear sablier; + address sender; + uint128 totalAmount; + address asset; + bool cancelable; + bool transferable; + LockupLinear.Timestamps timestamps; + LockupLinear.Broker broker; + } + struct Hat { uint32 maxSupply; string details; string imageURI; bool isMutable; address wearer; + SablierStreamParams[] sablierParams; // Optional Sablier stream parameters } struct CreateTreeParams { @@ -44,36 +59,6 @@ contract DecentHats_0_1_0 { salt = keccak256(concatenatedSaltInput); } - function createTopHat( - IHats _hatsProtocol, - string memory _topHatDetails, - string memory _topHatImageURI - ) internal returns (uint256) { - return - _hatsProtocol.mintTopHat( - address(this), - _topHatDetails, - _topHatImageURI - ); - } - - function createAccount( - IERC6551Registry _registry, - address _hatsAccountImplementation, - bytes32 salt, - address protocolAddress, - uint256 hatId - ) internal returns (address) { - return - _registry.createAccount( - _hatsAccountImplementation, - salt, - block.chainid, - protocolAddress, - hatId - ); - } - function updateKeyValuePairs( address _keyValuePairs, uint256 topHatId @@ -113,7 +98,47 @@ contract DecentHats_0_1_0 { ); } - function createHatAccountMint( + function createAccount( + IERC6551Registry _registry, + address _hatsAccountImplementation, + bytes32 salt, + address protocolAddress, + uint256 hatId + ) internal returns (address) { + return + _registry.createAccount( + _hatsAccountImplementation, + salt, + block.chainid, + protocolAddress, + hatId + ); + } + + function createTopHatAndAccount( + IHats _hatsProtocol, + string memory _topHatDetails, + string memory _topHatImageURI, + IERC6551Registry _registry, + address _hatsAccountImplementation, + bytes32 salt + ) internal returns (uint256 topHatId, address topHatAccount) { + topHatId = _hatsProtocol.mintTopHat( + address(this), + _topHatDetails, + _topHatImageURI + ); + + topHatAccount = createAccount( + _registry, + _hatsAccountImplementation, + salt, + address(_hatsProtocol), + topHatId + ); + } + + function createHatAndAccountAndMintAndStreams( IHats hatsProtocol, uint256 adminHatId, Hat calldata hat, @@ -135,26 +160,43 @@ contract DecentHats_0_1_0 { if (hat.wearer != address(0)) { hatsProtocol.mintHat(hatId, hat.wearer); } - } - function handleHats( - IHats _hatsProtocol, - IERC6551Registry _registry, - address _hatsAccountImplementation, - bytes32 salt, - address topHatAccount, - uint256 adminHatId, - Hat[] calldata _hats - ) internal { - for (uint256 i = 0; i < _hats.length; ) { - createHatAccountMint( - _hatsProtocol, - adminHatId, - _hats[i], - topHatAccount, - _registry, - _hatsAccountImplementation, - salt + for (uint256 i = 0; i < hat.sablierParams.length; ) { + SablierStreamParams memory sablierParams = hat.sablierParams[i]; + + // Approve tokens for Sablier + IAvatar(msg.sender).execTransactionFromModule( + sablierParams.asset, + 0, + abi.encodeWithSignature( + "approve(address,uint256)", + address(sablierParams.sablier), + sablierParams.totalAmount + ), + Enum.Operation.Call + ); + + LockupLinear.CreateWithTimestamps memory params = LockupLinear + .CreateWithTimestamps({ + sender: sablierParams.sender, + recipient: accountAddress, + totalAmount: sablierParams.totalAmount, + asset: IERC20(sablierParams.asset), + cancelable: sablierParams.cancelable, + transferable: sablierParams.transferable, + timestamps: sablierParams.timestamps, + broker: sablierParams.broker + }); + + // Proxy the Sablier call through IAvatar + IAvatar(msg.sender).execTransactionFromModule( + address(sablierParams.sablier), + 0, + abi.encodeWithSignature( + "createWithTimestamps((address,address,uint128,address,bool,bool,(uint40,uint40,uint40),(address,uint256)))", + params + ), + Enum.Operation.Call ); unchecked { @@ -165,22 +207,19 @@ contract DecentHats_0_1_0 { function createAndDeclareTree(CreateTreeParams calldata params) public { bytes32 salt = getSalt(); - uint256 topHatId = createTopHat( + + (uint256 topHatId, address topHatAccount) = createTopHatAndAccount( params.hatsProtocol, params.topHatDetails, - params.topHatImageURI - ); - address topHatAccount = createAccount( + params.topHatImageURI, params.registry, params.hatsAccountImplementation, - salt, - address(params.hatsProtocol), - topHatId + salt ); updateKeyValuePairs(params.keyValuePairs, topHatId); - (uint256 adminHatId, ) = createHatAccountMint( + (uint256 adminHatId, ) = createHatAndAccountAndMintAndStreams( params.hatsProtocol, topHatId, params.adminHat, @@ -190,15 +229,21 @@ contract DecentHats_0_1_0 { salt ); - handleHats( - params.hatsProtocol, - params.registry, - params.hatsAccountImplementation, - salt, - topHatAccount, - adminHatId, - params.hats - ); + for (uint256 i = 0; i < params.hats.length; ) { + createHatAndAccountAndMintAndStreams( + params.hatsProtocol, + adminHatId, + params.hats[i], + topHatAccount, + params.registry, + params.hatsAccountImplementation, + salt + ); + + unchecked { + ++i; + } + } params.hatsProtocol.transferHat(topHatId, address(this), msg.sender); } diff --git a/contracts/interfaces/sablier/ISablierV2LockupLinear.sol b/contracts/interfaces/sablier/ISablierV2LockupLinear.sol new file mode 100644 index 00000000..0aa6cac9 --- /dev/null +++ b/contracts/interfaces/sablier/ISablierV2LockupLinear.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {LockupLinear} from "./LockupLinear.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +interface ISablierV2LockupLinear { + function createWithTimestamps( + LockupLinear.CreateWithTimestamps calldata params + ) external returns (uint256 streamId); +} diff --git a/contracts/interfaces/sablier/LockupLinear.sol b/contracts/interfaces/sablier/LockupLinear.sol new file mode 100644 index 00000000..0225d060 --- /dev/null +++ b/contracts/interfaces/sablier/LockupLinear.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +library LockupLinear { + struct CreateWithTimestamps { + address sender; + address recipient; + uint128 totalAmount; + IERC20 asset; + bool cancelable; + bool transferable; + Timestamps timestamps; + Broker broker; + } + + struct Timestamps { + uint40 start; + uint40 cliff; + uint40 end; + } + + struct Broker { + address account; + uint256 fee; + } +} diff --git a/contracts/mock/ERC6551Registry.sol b/contracts/mocks/ERC6551Registry.sol similarity index 100% rename from contracts/mock/ERC6551Registry.sol rename to contracts/mocks/ERC6551Registry.sol diff --git a/contracts/mock/MockContract.sol b/contracts/mocks/MockContract.sol similarity index 100% rename from contracts/mock/MockContract.sol rename to contracts/mocks/MockContract.sol diff --git a/contracts/mocks/MockERC20.sol b/contracts/mocks/MockERC20.sol new file mode 100644 index 00000000..b0b50bca --- /dev/null +++ b/contracts/mocks/MockERC20.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity =0.8.19; + +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +contract MockERC20 is ERC20 { + constructor(string memory name, string memory symbol) ERC20(name, symbol) {} + + function mint(address to, uint256 amount) public { + _mint(to, amount); + } +} diff --git a/contracts/mock/MockERC721.sol b/contracts/mocks/MockERC721.sol similarity index 100% rename from contracts/mock/MockERC721.sol rename to contracts/mocks/MockERC721.sol diff --git a/contracts/mock/MockHats.sol b/contracts/mocks/MockHats.sol similarity index 100% rename from contracts/mock/MockHats.sol rename to contracts/mocks/MockHats.sol diff --git a/contracts/mock/MockHatsAccount.sol b/contracts/mocks/MockHatsAccount.sol similarity index 100% rename from contracts/mock/MockHatsAccount.sol rename to contracts/mocks/MockHatsAccount.sol diff --git a/contracts/mocks/MockSablierV2LockupLinear.sol b/contracts/mocks/MockSablierV2LockupLinear.sol new file mode 100644 index 00000000..7d737bb4 --- /dev/null +++ b/contracts/mocks/MockSablierV2LockupLinear.sol @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: MIT +pragma solidity =0.8.19; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "../interfaces/sablier/ISablierV2LockupLinear.sol"; +import {LockupLinear} from "../interfaces/sablier/LockupLinear.sol"; + +contract MockSablierV2LockupLinear is ISablierV2LockupLinear { + // Define the Stream struct here + struct Stream { + address sender; + address recipient; + uint128 totalAmount; + address asset; + bool cancelable; + bool transferable; + uint40 startTime; + uint40 cliffTime; + uint40 endTime; + } + + mapping(uint256 => Stream) public streams; + uint256 public nextStreamId = 1; + + // Add this event declaration at the contract level + event StreamCreated( + uint256 streamId, + address indexed sender, + address indexed recipient, + uint128 totalAmount, + address indexed asset, + bool cancelable, + bool transferable, + uint40 startTime, + uint40 cliffTime, + uint40 endTime + ); + + function createWithTimestamps( + LockupLinear.CreateWithTimestamps calldata params + ) external override returns (uint256 streamId) { + require( + params.asset.transferFrom( + msg.sender, + address(this), + params.totalAmount + ), + "Token transfer failed" + ); + + streamId = nextStreamId++; + streams[streamId] = Stream({ + sender: params.sender, + recipient: params.recipient, + totalAmount: params.totalAmount, + asset: address(params.asset), + cancelable: params.cancelable, + transferable: params.transferable, + startTime: params.timestamps.start, + cliffTime: params.timestamps.cliff, + endTime: params.timestamps.end + }); + + // Emit the StreamCreated event + emit StreamCreated( + streamId, + params.sender, + params.recipient, + params.totalAmount, + address(params.asset), + params.cancelable, + params.transferable, + params.timestamps.start, + params.timestamps.cliff, + params.timestamps.end + ); + + return streamId; + } + + function getStream(uint256 streamId) external view returns (Stream memory) { + return streams[streamId]; + } + + function withdrawableAmountOf( + uint256 streamId + ) public view returns (uint128) { + Stream memory stream = streams[streamId]; + if (block.timestamp <= stream.startTime) { + return 0; + } + if (block.timestamp >= stream.endTime) { + return stream.totalAmount; + } + return + uint128( + (stream.totalAmount * (block.timestamp - stream.startTime)) / + (stream.endTime - stream.startTime) + ); + } + + function withdraw(uint256 streamId, uint128 amount) external { + Stream storage stream = streams[streamId]; + require(msg.sender == stream.recipient, "Only recipient can withdraw"); + require( + amount <= withdrawableAmountOf(streamId), + "Insufficient withdrawable amount" + ); + + stream.totalAmount -= amount; + IERC20(stream.asset).transfer(stream.recipient, amount); + } + + function cancel(uint256 streamId) external { + Stream memory stream = streams[streamId]; + require(stream.cancelable, "Stream is not cancelable"); + require(msg.sender == stream.sender, "Only sender can cancel"); + + uint128 withdrawableAmount = withdrawableAmountOf(streamId); + uint128 refundAmount = stream.totalAmount - withdrawableAmount; + + delete streams[streamId]; + + if (withdrawableAmount > 0) { + IERC20(stream.asset).transfer(stream.recipient, withdrawableAmount); + } + if (refundAmount > 0) { + IERC20(stream.asset).transfer(stream.sender, refundAmount); + } + } + + function renounce(uint256 streamId) external { + Stream memory stream = streams[streamId]; + require(msg.sender == stream.recipient, "Only recipient can renounce"); + + uint128 withdrawableAmount = withdrawableAmountOf(streamId); + uint128 refundAmount = stream.totalAmount - withdrawableAmount; + + delete streams[streamId]; + + if (withdrawableAmount > 0) { + IERC20(stream.asset).transfer(stream.recipient, withdrawableAmount); + } + if (refundAmount > 0) { + IERC20(stream.asset).transfer(stream.sender, refundAmount); + } + } + + function transferFrom(uint256 streamId, address recipient) external { + Stream storage stream = streams[streamId]; + require(stream.transferable, "Stream is not transferable"); + require( + msg.sender == stream.recipient, + "Only current recipient can transfer" + ); + + stream.recipient = recipient; + } +} diff --git a/contracts/mock/MockVotingStrategy.sol b/contracts/mocks/MockVotingStrategy.sol similarity index 100% rename from contracts/mock/MockVotingStrategy.sol rename to contracts/mocks/MockVotingStrategy.sol diff --git a/deployments/base/DecentHats_0_1_0.json b/deployments/base/DecentHats_0_1_0.json index 085ee438..297f78a1 100644 --- a/deployments/base/DecentHats_0_1_0.json +++ b/deployments/base/DecentHats_0_1_0.json @@ -1,5 +1,5 @@ { - "address": "0x47aB70e4e8E8e957c6373Ade97dE224a46b89896", + "address": "0xfEFe8C7E647E66D1612Aea29f9A58172823473E0", "abi": [ { "inputs": [], @@ -74,6 +74,82 @@ "internalType": "address", "name": "wearer", "type": "address" + }, + { + "components": [ + { + "internalType": "contract ISablierV2LockupLinear", + "name": "sablier", + "type": "address" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint128", + "name": "totalAmount", + "type": "uint128" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "bool", + "name": "cancelable", + "type": "bool" + }, + { + "internalType": "bool", + "name": "transferable", + "type": "bool" + }, + { + "components": [ + { + "internalType": "uint40", + "name": "start", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "cliff", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "end", + "type": "uint40" + } + ], + "internalType": "struct LockupLinear.Timestamps", + "name": "timestamps", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "fee", + "type": "uint256" + } + ], + "internalType": "struct LockupLinear.Broker", + "name": "broker", + "type": "tuple" + } + ], + "internalType": "struct DecentHats_0_1_0.SablierStreamParams[]", + "name": "sablierParams", + "type": "tuple[]" } ], "internalType": "struct DecentHats_0_1_0.Hat", @@ -106,6 +182,82 @@ "internalType": "address", "name": "wearer", "type": "address" + }, + { + "components": [ + { + "internalType": "contract ISablierV2LockupLinear", + "name": "sablier", + "type": "address" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint128", + "name": "totalAmount", + "type": "uint128" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "bool", + "name": "cancelable", + "type": "bool" + }, + { + "internalType": "bool", + "name": "transferable", + "type": "bool" + }, + { + "components": [ + { + "internalType": "uint40", + "name": "start", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "cliff", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "end", + "type": "uint40" + } + ], + "internalType": "struct LockupLinear.Timestamps", + "name": "timestamps", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "fee", + "type": "uint256" + } + ], + "internalType": "struct LockupLinear.Broker", + "name": "broker", + "type": "tuple" + } + ], + "internalType": "struct DecentHats_0_1_0.SablierStreamParams[]", + "name": "sablierParams", + "type": "tuple[]" } ], "internalType": "struct DecentHats_0_1_0.Hat[]", @@ -124,28 +276,28 @@ "type": "function" } ], - "transactionHash": "0x8502a87a653aa57631b14ec5e7b4957765b3f128e6d0c720830e10b0a0947b1f", + "transactionHash": "0x1fc38c8f5da2e0e6b24a13b6799c8c5a9ec569034380afb572014941426742ce", "receipt": { "to": null, "from": "0xb5Ca125166C1987A35EDD550E16846Fa1e1D9bB3", - "contractAddress": "0x47aB70e4e8E8e957c6373Ade97dE224a46b89896", - "transactionIndex": 72, - "gasUsed": "848547", + "contractAddress": "0xfEFe8C7E647E66D1612Aea29f9A58172823473E0", + "transactionIndex": 134, + "gasUsed": "1184549", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x53273291dce023ed7c72aa7647bd3d01cad2dfe4cd735dc2d0832271738ca39d", - "transactionHash": "0x8502a87a653aa57631b14ec5e7b4957765b3f128e6d0c720830e10b0a0947b1f", + "blockHash": "0x6b3e73c7394fc01da9e070b1f303a87428ed45c28fd33002d1aa8af5e90ded4f", + "transactionHash": "0x1fc38c8f5da2e0e6b24a13b6799c8c5a9ec569034380afb572014941426742ce", "logs": [], - "blockNumber": 16901239, - "cumulativeGasUsed": "8443975", + "blockNumber": 19648644, + "cumulativeGasUsed": "19643187", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "88a7dc38a4aa54f89c0bd740dfe90545", - "metadata": "{\"compiler\":{\"version\":\"0.8.19+commit.7dd6d404\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"NAME\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contract IHats\",\"name\":\"hatsProtocol\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"hatsAccountImplementation\",\"type\":\"address\"},{\"internalType\":\"contract IERC6551Registry\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"keyValuePairs\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"topHatDetails\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"topHatImageURI\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxSupply\",\"type\":\"uint32\"},{\"internalType\":\"string\",\"name\":\"details\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"imageURI\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isMutable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"wearer\",\"type\":\"address\"}],\"internalType\":\"struct DecentHats_0_1_0.Hat\",\"name\":\"adminHat\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxSupply\",\"type\":\"uint32\"},{\"internalType\":\"string\",\"name\":\"details\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"imageURI\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isMutable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"wearer\",\"type\":\"address\"}],\"internalType\":\"struct DecentHats_0_1_0.Hat[]\",\"name\":\"hats\",\"type\":\"tuple[]\"}],\"internalType\":\"struct DecentHats_0_1_0.CreateTreeParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"createAndDeclareTree\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/DecentHats_0_1_0.sol\":\"DecentHats_0_1_0\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.7.0 <0.9.0;\\n\\n/// @title Enum - Collection of enums\\n/// @author Richard Meissner - \\ncontract Enum {\\n enum Operation {Call, DelegateCall}\\n}\\n\",\"keccak256\":\"0x473e45b1a5cc47be494b0e123c9127f0c11c1e0992a321ae5a644c0bfdb2c14f\",\"license\":\"LGPL-3.0-only\"},\"@gnosis.pm/zodiac/contracts/interfaces/IAvatar.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\n\\n/// @title Zodiac Avatar - A contract that manages modules that can execute transactions via this contract.\\npragma solidity >=0.7.0 <0.9.0;\\n\\nimport \\\"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\\\";\\n\\ninterface IAvatar {\\n event EnabledModule(address module);\\n event DisabledModule(address module);\\n event ExecutionFromModuleSuccess(address indexed module);\\n event ExecutionFromModuleFailure(address indexed module);\\n\\n /// @dev Enables a module on the avatar.\\n /// @notice Can only be called by the avatar.\\n /// @notice Modules should be stored as a linked list.\\n /// @notice Must emit EnabledModule(address module) if successful.\\n /// @param module Module to be enabled.\\n function enableModule(address module) external;\\n\\n /// @dev Disables a module on the avatar.\\n /// @notice Can only be called by the avatar.\\n /// @notice Must emit DisabledModule(address module) if successful.\\n /// @param prevModule Address that pointed to the module to be removed in the linked list\\n /// @param module Module to be removed.\\n function disableModule(address prevModule, address module) external;\\n\\n /// @dev Allows a Module to execute a transaction.\\n /// @notice Can only be called by an enabled module.\\n /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.\\n /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.\\n /// @param to Destination address of module transaction.\\n /// @param value Ether value of module transaction.\\n /// @param data Data payload of module transaction.\\n /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.\\n function execTransactionFromModule(\\n address to,\\n uint256 value,\\n bytes memory data,\\n Enum.Operation operation\\n ) external returns (bool success);\\n\\n /// @dev Allows a Module to execute a transaction and return data\\n /// @notice Can only be called by an enabled module.\\n /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.\\n /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.\\n /// @param to Destination address of module transaction.\\n /// @param value Ether value of module transaction.\\n /// @param data Data payload of module transaction.\\n /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.\\n function execTransactionFromModuleReturnData(\\n address to,\\n uint256 value,\\n bytes memory data,\\n Enum.Operation operation\\n ) external returns (bool success, bytes memory returnData);\\n\\n /// @dev Returns if an module is enabled\\n /// @return True if the module is enabled\\n function isModuleEnabled(address module) external view returns (bool);\\n\\n /// @dev Returns array of modules.\\n /// @param start Start of the page.\\n /// @param pageSize Maximum number of modules that should be returned.\\n /// @return array Array of modules.\\n /// @return next Start of the next page.\\n function getModulesPaginated(address start, uint256 pageSize)\\n external\\n view\\n returns (address[] memory array, address next);\\n}\\n\",\"keccak256\":\"0xcd5508ffe596eef8fbccfd5fc4f10a34397773547ce64e212d48b5212865ec1f\",\"license\":\"LGPL-3.0-only\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n}\\n\",\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\"},\"contracts/DecentHats_0_1_0.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity =0.8.19;\\n\\nimport {Enum} from \\\"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\\\";\\nimport {IAvatar} from \\\"@gnosis.pm/zodiac/contracts/interfaces/IAvatar.sol\\\";\\nimport {Strings} from \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\nimport {IERC6551Registry} from \\\"./interfaces/IERC6551Registry.sol\\\";\\nimport {IHats} from \\\"./interfaces/hats/IHats.sol\\\";\\n\\ncontract DecentHats_0_1_0 {\\n string public constant NAME = \\\"DecentHats_0_1_0\\\";\\n\\n struct Hat {\\n uint32 maxSupply;\\n string details;\\n string imageURI;\\n bool isMutable;\\n address wearer;\\n }\\n\\n struct CreateTreeParams {\\n IHats hatsProtocol;\\n address hatsAccountImplementation;\\n IERC6551Registry registry;\\n address keyValuePairs;\\n string topHatDetails;\\n string topHatImageURI;\\n Hat adminHat;\\n Hat[] hats;\\n }\\n\\n function getSalt() internal view returns (bytes32 salt) {\\n uint256 chainId;\\n assembly {\\n chainId := chainid()\\n }\\n\\n bytes memory concatenatedSaltInput = abi.encodePacked(\\n NAME,\\n chainId,\\n address(this)\\n );\\n\\n salt = keccak256(concatenatedSaltInput);\\n }\\n\\n function createTopHat(\\n IHats _hatsProtocol,\\n string memory _topHatDetails,\\n string memory _topHatImageURI\\n ) internal returns (uint256) {\\n return\\n _hatsProtocol.mintTopHat(\\n address(this),\\n _topHatDetails,\\n _topHatImageURI\\n );\\n }\\n\\n function createAccount(\\n IERC6551Registry _registry,\\n address _hatsAccountImplementation,\\n bytes32 salt,\\n address protocolAddress,\\n uint256 hatId\\n ) internal returns (address) {\\n return\\n _registry.createAccount(\\n _hatsAccountImplementation,\\n salt,\\n block.chainid,\\n protocolAddress,\\n hatId\\n );\\n }\\n\\n function updateKeyValuePairs(\\n address _keyValuePairs,\\n uint256 topHatId\\n ) internal {\\n string[] memory keys = new string[](1);\\n string[] memory values = new string[](1);\\n keys[0] = \\\"topHatId\\\";\\n values[0] = Strings.toString(topHatId);\\n\\n IAvatar(msg.sender).execTransactionFromModule(\\n _keyValuePairs,\\n 0,\\n abi.encodeWithSignature(\\n \\\"updateValues(string[],string[])\\\",\\n keys,\\n values\\n ),\\n Enum.Operation.Call\\n );\\n }\\n\\n function createHat(\\n IHats _hatsProtocol,\\n uint256 adminHatId,\\n Hat memory _hat,\\n address topHatAccount\\n ) internal returns (uint256) {\\n return\\n _hatsProtocol.createHat(\\n adminHatId,\\n _hat.details,\\n _hat.maxSupply,\\n topHatAccount,\\n topHatAccount,\\n _hat.isMutable,\\n _hat.imageURI\\n );\\n }\\n\\n function createHatAccountMint(\\n IHats hatsProtocol,\\n uint256 adminHatId,\\n Hat calldata hat,\\n address topHatAccount,\\n IERC6551Registry registry,\\n address hatsAccountImplementation,\\n bytes32 salt\\n ) internal returns (uint256 hatId, address accountAddress) {\\n hatId = createHat(hatsProtocol, adminHatId, hat, topHatAccount);\\n\\n accountAddress = createAccount(\\n registry,\\n hatsAccountImplementation,\\n salt,\\n address(hatsProtocol),\\n hatId\\n );\\n\\n if (hat.wearer != address(0)) {\\n hatsProtocol.mintHat(hatId, hat.wearer);\\n }\\n }\\n\\n function handleHats(\\n IHats _hatsProtocol,\\n IERC6551Registry _registry,\\n address _hatsAccountImplementation,\\n bytes32 salt,\\n address topHatAccount,\\n uint256 adminHatId,\\n Hat[] calldata _hats\\n ) internal {\\n for (uint256 i = 0; i < _hats.length; ) {\\n createHatAccountMint(\\n _hatsProtocol,\\n adminHatId,\\n _hats[i],\\n topHatAccount,\\n _registry,\\n _hatsAccountImplementation,\\n salt\\n );\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n function createAndDeclareTree(CreateTreeParams calldata params) public {\\n bytes32 salt = getSalt();\\n uint256 topHatId = createTopHat(\\n params.hatsProtocol,\\n params.topHatDetails,\\n params.topHatImageURI\\n );\\n address topHatAccount = createAccount(\\n params.registry,\\n params.hatsAccountImplementation,\\n salt,\\n address(params.hatsProtocol),\\n topHatId\\n );\\n\\n updateKeyValuePairs(params.keyValuePairs, topHatId);\\n\\n (uint256 adminHatId, ) = createHatAccountMint(\\n params.hatsProtocol,\\n topHatId,\\n params.adminHat,\\n topHatAccount,\\n params.registry,\\n params.hatsAccountImplementation,\\n salt\\n );\\n\\n handleHats(\\n params.hatsProtocol,\\n params.registry,\\n params.hatsAccountImplementation,\\n salt,\\n topHatAccount,\\n adminHatId,\\n params.hats\\n );\\n\\n params.hatsProtocol.transferHat(topHatId, address(this), msg.sender);\\n }\\n}\\n\",\"keccak256\":\"0xd7dbbda48b0f7eedeef3882aab51e93c4881a47bcb09b2f9a20989d22259f027\",\"license\":\"MIT\"},\"contracts/interfaces/IERC6551Registry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IERC6551Registry {\\n /**\\n * @dev Creates a token bound account for a non-fungible token.\\n *\\n * If account has already been created, returns the account address without calling create2.\\n *\\n * Emits ERC6551AccountCreated event.\\n *\\n * @return account The address of the token bound account\\n */\\n function createAccount(\\n address implementation,\\n bytes32 salt,\\n uint256 chainId,\\n address tokenContract,\\n uint256 tokenId\\n ) external returns (address account);\\n}\\n\",\"keccak256\":\"0x64c52de8a8e68398e61dd8b42dda8e9af8cf6abf93bb85629c322440991ea568\",\"license\":\"MIT\"},\"contracts/interfaces/hats/IHats.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0\\n// Copyright (C) 2023 Haberdasher Labs\\n//\\n// This program is free software: you can redistribute it and/or modify\\n// it under the terms of the GNU Affero General Public License as published by\\n// the Free Software Foundation, either version 3 of the License, or\\n// (at your option) any later version.\\n//\\n// This program is distributed in the hope that it will be useful,\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\\n// GNU Affero General Public License for more details.\\n//\\n// You should have received a copy of the GNU Affero General Public License\\n// along with this program. If not, see .\\n\\npragma solidity >=0.8.13;\\n\\ninterface IHats {\\n function mintTopHat(\\n address _target,\\n string memory _details,\\n string memory _imageURI\\n ) external returns (uint256 topHatId);\\n\\n function createHat(\\n uint256 _admin,\\n string calldata _details,\\n uint32 _maxSupply,\\n address _eligibility,\\n address _toggle,\\n bool _mutable,\\n string calldata _imageURI\\n ) external returns (uint256 newHatId);\\n\\n function mintHat(\\n uint256 _hatId,\\n address _wearer\\n ) external returns (bool success);\\n\\n function transferHat(uint256 _hatId, address _from, address _to) external;\\n}\\n\",\"keccak256\":\"0x8e35022f5c0fcf0059033abec78ec890f0cf3bbac09d6d24051cff9679239511\",\"license\":\"AGPL-3.0\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50610e63806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063a3f4df7e1461003b578063c1bce50714610080575b600080fd5b61006a6040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b81525081565b60405161007791906108a5565b60405180910390f35b61009361008e3660046108bf565b610095565b005b600061009f61029d565b9050600061013c6100b36020850185610913565b6100c06080860186610930565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506101029250505060a0870187610930565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061030192505050565b905060006101776101536060860160408701610913565b6101636040870160208801610913565b856101716020890189610913565b8661037f565b905061019261018c6080860160608701610913565b83610415565b60006101d96101a46020870187610913565b846101b260c089018961098e565b856101c360608b0160408c01610913565b6101d360408c0160208d01610913565b8a610595565b5090506102216101ec6020870187610913565b6101fc6060880160408901610913565b61020c6040890160208a01610913565b87868661021c60e08d018d6109ae565b61067b565b61022e6020860186610913565b6040516329287c1b60e21b8152600481018590523060248201523360448201526001600160a01b03919091169063a4a1f06c90606401600060405180830381600087803b15801561027e57600080fd5b505af1158015610292573d6000803e3d6000fd5b505050505050505050565b60008046905060006040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b81525082306040516020016102e2939291906109f8565b60408051601f1981840301815291905280516020909101209392505050565b604051631a64dfad60e01b81526000906001600160a01b03851690631a64dfad9061033490309087908790600401610a31565b6020604051808303816000875af1158015610353573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103779190610a67565b949350505050565b604051638a54c52f60e01b81526001600160a01b0385811660048301526024820185905246604483015283811660648301526084820183905260009190871690638a54c52f9060a4016020604051808303816000875af11580156103e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061040b9190610a80565b9695505050505050565b604080516001808252818301909252600091816020015b606081526020019060019003908161042c57505060408051600180825281830190925291925060009190602082015b606081526020019060019003908161045b579050509050604051806040016040528060088152602001671d1bdc12185d125960c21b815250826000815181106104a6576104a6610ab3565b60200260200101819052506104ba836106c2565b816000815181106104cd576104cd610ab3565b6020026020010181905250336001600160a01b031663468721a785600085856040516024016104fd929190610b1e565b60408051601f198184030181529181526020820180516001600160e01b031663579374b960e11b1790525160e085901b6001600160e01b031916815261054b93929190600090600401610b43565b6020604051808303816000875af115801561056a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058e9190610ba7565b5050505050565b6000806105ac89896105a68a610c85565b896107c3565b91506105bb8585858c8661037f565b905060006105cf60a0890160808a01610913565b6001600160a01b03161461066f576001600160a01b03891663641f776e836105fd60a08b0160808c01610913565b6040516001600160e01b031960e085901b16815260048101929092526001600160a01b031660248201526044016020604051808303816000875af1158015610649573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066d9190610ba7565b505b97509795505050505050565b60005b81811015610292576106b8898585858581811061069d5761069d610ab3565b90506020028101906106af919061098e565b888c8c8c610595565b505060010161067e565b6060816000036106e95750506040805180820190915260018152600360fc1b602082015290565b8160005b811561071357806106fd81610d46565b915061070c9050600a83610d75565b91506106ed565b60008167ffffffffffffffff81111561072e5761072e610a9d565b6040519080825280601f01601f191660200182016040528015610758576020820181803683370190505b5090505b84156103775761076d600183610d89565b915061077a600a86610da2565b610785906030610db6565b60f81b81838151811061079a5761079a610ab3565b60200101906001600160f81b031916908160001a9053506107bc600a86610d75565b945061075c565b6020820151825160608401516040808601519051635829492f60e11b81526000946001600160a01b038a169463b052925e94610809948b948a9283929091600401610dc9565b6020604051808303816000875af1158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c9190610a67565b95945050505050565b60005b83811015610870578181015183820152602001610858565b50506000910152565b60008151808452610891816020860160208601610855565b601f01601f19169290920160200192915050565b6020815260006108b86020830184610879565b9392505050565b6000602082840312156108d157600080fd5b813567ffffffffffffffff8111156108e857600080fd5b820161010081850312156108b857600080fd5b6001600160a01b038116811461091057600080fd5b50565b60006020828403121561092557600080fd5b81356108b8816108fb565b6000808335601e1984360301811261094757600080fd5b83018035915067ffffffffffffffff82111561096257600080fd5b60200191503681900382131561097757600080fd5b9250929050565b8035610989816108fb565b919050565b60008235609e198336030181126109a457600080fd5b9190910192915050565b6000808335601e198436030181126109c557600080fd5b83018035915067ffffffffffffffff8211156109e057600080fd5b6020019150600581901b360382131561097757600080fd5b60008451610a0a818460208901610855565b919091019283525060601b6bffffffffffffffffffffffff19166020820152603401919050565b6001600160a01b0384168152606060208201819052600090610a5590830185610879565b828103604084015261040b8185610879565b600060208284031215610a7957600080fd5b5051919050565b600060208284031215610a9257600080fd5b81516108b8816108fb565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501808196508360051b8101915082860160005b85811015610b11578284038952610aff848351610879565b98850198935090840190600101610ae7565b5091979650505050505050565b604081526000610b316040830185610ac9565b828103602084015261084c8185610ac9565b60018060a01b0385168152836020820152608060408201526000610b6a6080830185610879565b905060028310610b8a57634e487b7160e01b600052602160045260246000fd5b82606083015295945050505050565b801515811461091057600080fd5b600060208284031215610bb957600080fd5b81516108b881610b99565b60405160a0810167ffffffffffffffff81118282101715610be757610be7610a9d565b60405290565b600082601f830112610bfe57600080fd5b813567ffffffffffffffff80821115610c1957610c19610a9d565b604051601f8301601f19908116603f01168101908282118183101715610c4157610c41610a9d565b81604052838152866020858801011115610c5a57600080fd5b836020870160208301376000602085830101528094505050505092915050565b803561098981610b99565b600060a08236031215610c9757600080fd5b610c9f610bc4565b823563ffffffff81168114610cb357600080fd5b8152602083013567ffffffffffffffff80821115610cd057600080fd5b610cdc36838701610bed565b60208401526040850135915080821115610cf557600080fd5b50610d0236828601610bed565b604083015250610d1460608401610c7a565b6060820152610d256080840161097e565b608082015292915050565b634e487b7160e01b600052601160045260246000fd5b600060018201610d5857610d58610d30565b5060010190565b634e487b7160e01b600052601260045260246000fd5b600082610d8457610d84610d5f565b500490565b81810381811115610d9c57610d9c610d30565b92915050565b600082610db157610db1610d5f565b500690565b80820180821115610d9c57610d9c610d30565b87815260e060208201526000610de260e0830189610879565b63ffffffff881660408401526001600160a01b0387811660608501528616608084015284151560a084015282810360c0840152610e1f8185610879565b9a995050505050505050505056fea264697066735822122040470770e7f603d20cdea8118401756a0349e1cdc776519095ccf844ef03c2cd64736f6c63430008130033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c8063a3f4df7e1461003b578063c1bce50714610080575b600080fd5b61006a6040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b81525081565b60405161007791906108a5565b60405180910390f35b61009361008e3660046108bf565b610095565b005b600061009f61029d565b9050600061013c6100b36020850185610913565b6100c06080860186610930565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506101029250505060a0870187610930565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061030192505050565b905060006101776101536060860160408701610913565b6101636040870160208801610913565b856101716020890189610913565b8661037f565b905061019261018c6080860160608701610913565b83610415565b60006101d96101a46020870187610913565b846101b260c089018961098e565b856101c360608b0160408c01610913565b6101d360408c0160208d01610913565b8a610595565b5090506102216101ec6020870187610913565b6101fc6060880160408901610913565b61020c6040890160208a01610913565b87868661021c60e08d018d6109ae565b61067b565b61022e6020860186610913565b6040516329287c1b60e21b8152600481018590523060248201523360448201526001600160a01b03919091169063a4a1f06c90606401600060405180830381600087803b15801561027e57600080fd5b505af1158015610292573d6000803e3d6000fd5b505050505050505050565b60008046905060006040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b81525082306040516020016102e2939291906109f8565b60408051601f1981840301815291905280516020909101209392505050565b604051631a64dfad60e01b81526000906001600160a01b03851690631a64dfad9061033490309087908790600401610a31565b6020604051808303816000875af1158015610353573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103779190610a67565b949350505050565b604051638a54c52f60e01b81526001600160a01b0385811660048301526024820185905246604483015283811660648301526084820183905260009190871690638a54c52f9060a4016020604051808303816000875af11580156103e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061040b9190610a80565b9695505050505050565b604080516001808252818301909252600091816020015b606081526020019060019003908161042c57505060408051600180825281830190925291925060009190602082015b606081526020019060019003908161045b579050509050604051806040016040528060088152602001671d1bdc12185d125960c21b815250826000815181106104a6576104a6610ab3565b60200260200101819052506104ba836106c2565b816000815181106104cd576104cd610ab3565b6020026020010181905250336001600160a01b031663468721a785600085856040516024016104fd929190610b1e565b60408051601f198184030181529181526020820180516001600160e01b031663579374b960e11b1790525160e085901b6001600160e01b031916815261054b93929190600090600401610b43565b6020604051808303816000875af115801561056a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058e9190610ba7565b5050505050565b6000806105ac89896105a68a610c85565b896107c3565b91506105bb8585858c8661037f565b905060006105cf60a0890160808a01610913565b6001600160a01b03161461066f576001600160a01b03891663641f776e836105fd60a08b0160808c01610913565b6040516001600160e01b031960e085901b16815260048101929092526001600160a01b031660248201526044016020604051808303816000875af1158015610649573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066d9190610ba7565b505b97509795505050505050565b60005b81811015610292576106b8898585858581811061069d5761069d610ab3565b90506020028101906106af919061098e565b888c8c8c610595565b505060010161067e565b6060816000036106e95750506040805180820190915260018152600360fc1b602082015290565b8160005b811561071357806106fd81610d46565b915061070c9050600a83610d75565b91506106ed565b60008167ffffffffffffffff81111561072e5761072e610a9d565b6040519080825280601f01601f191660200182016040528015610758576020820181803683370190505b5090505b84156103775761076d600183610d89565b915061077a600a86610da2565b610785906030610db6565b60f81b81838151811061079a5761079a610ab3565b60200101906001600160f81b031916908160001a9053506107bc600a86610d75565b945061075c565b6020820151825160608401516040808601519051635829492f60e11b81526000946001600160a01b038a169463b052925e94610809948b948a9283929091600401610dc9565b6020604051808303816000875af1158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c9190610a67565b95945050505050565b60005b83811015610870578181015183820152602001610858565b50506000910152565b60008151808452610891816020860160208601610855565b601f01601f19169290920160200192915050565b6020815260006108b86020830184610879565b9392505050565b6000602082840312156108d157600080fd5b813567ffffffffffffffff8111156108e857600080fd5b820161010081850312156108b857600080fd5b6001600160a01b038116811461091057600080fd5b50565b60006020828403121561092557600080fd5b81356108b8816108fb565b6000808335601e1984360301811261094757600080fd5b83018035915067ffffffffffffffff82111561096257600080fd5b60200191503681900382131561097757600080fd5b9250929050565b8035610989816108fb565b919050565b60008235609e198336030181126109a457600080fd5b9190910192915050565b6000808335601e198436030181126109c557600080fd5b83018035915067ffffffffffffffff8211156109e057600080fd5b6020019150600581901b360382131561097757600080fd5b60008451610a0a818460208901610855565b919091019283525060601b6bffffffffffffffffffffffff19166020820152603401919050565b6001600160a01b0384168152606060208201819052600090610a5590830185610879565b828103604084015261040b8185610879565b600060208284031215610a7957600080fd5b5051919050565b600060208284031215610a9257600080fd5b81516108b8816108fb565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501808196508360051b8101915082860160005b85811015610b11578284038952610aff848351610879565b98850198935090840190600101610ae7565b5091979650505050505050565b604081526000610b316040830185610ac9565b828103602084015261084c8185610ac9565b60018060a01b0385168152836020820152608060408201526000610b6a6080830185610879565b905060028310610b8a57634e487b7160e01b600052602160045260246000fd5b82606083015295945050505050565b801515811461091057600080fd5b600060208284031215610bb957600080fd5b81516108b881610b99565b60405160a0810167ffffffffffffffff81118282101715610be757610be7610a9d565b60405290565b600082601f830112610bfe57600080fd5b813567ffffffffffffffff80821115610c1957610c19610a9d565b604051601f8301601f19908116603f01168101908282118183101715610c4157610c41610a9d565b81604052838152866020858801011115610c5a57600080fd5b836020870160208301376000602085830101528094505050505092915050565b803561098981610b99565b600060a08236031215610c9757600080fd5b610c9f610bc4565b823563ffffffff81168114610cb357600080fd5b8152602083013567ffffffffffffffff80821115610cd057600080fd5b610cdc36838701610bed565b60208401526040850135915080821115610cf557600080fd5b50610d0236828601610bed565b604083015250610d1460608401610c7a565b6060820152610d256080840161097e565b608082015292915050565b634e487b7160e01b600052601160045260246000fd5b600060018201610d5857610d58610d30565b5060010190565b634e487b7160e01b600052601260045260246000fd5b600082610d8457610d84610d5f565b500490565b81810381811115610d9c57610d9c610d30565b92915050565b600082610db157610db1610d5f565b500690565b80820180821115610d9c57610d9c610d30565b87815260e060208201526000610de260e0830189610879565b63ffffffff881660408401526001600160a01b0387811660608501528616608084015284151560a084015282810360c0840152610e1f8185610879565b9a995050505050505050505056fea264697066735822122040470770e7f603d20cdea8118401756a0349e1cdc776519095ccf844ef03c2cd64736f6c63430008130033", + "numDeployments": 2, + "solcInputHash": "512807b5d71481c693c202ae23158904", + "metadata": "{\"compiler\":{\"version\":\"0.8.19+commit.7dd6d404\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"NAME\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contract IHats\",\"name\":\"hatsProtocol\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"hatsAccountImplementation\",\"type\":\"address\"},{\"internalType\":\"contract IERC6551Registry\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"keyValuePairs\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"topHatDetails\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"topHatImageURI\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxSupply\",\"type\":\"uint32\"},{\"internalType\":\"string\",\"name\":\"details\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"imageURI\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isMutable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"wearer\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"contract ISablierV2LockupLinear\",\"name\":\"sablier\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint128\",\"name\":\"totalAmount\",\"type\":\"uint128\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"cancelable\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"transferable\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"uint40\",\"name\":\"start\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"cliff\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"end\",\"type\":\"uint40\"}],\"internalType\":\"struct LockupLinear.Timestamps\",\"name\":\"timestamps\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"}],\"internalType\":\"struct LockupLinear.Broker\",\"name\":\"broker\",\"type\":\"tuple\"}],\"internalType\":\"struct DecentHats_0_1_0.SablierStreamParams[]\",\"name\":\"sablierParams\",\"type\":\"tuple[]\"}],\"internalType\":\"struct DecentHats_0_1_0.Hat\",\"name\":\"adminHat\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxSupply\",\"type\":\"uint32\"},{\"internalType\":\"string\",\"name\":\"details\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"imageURI\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isMutable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"wearer\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"contract ISablierV2LockupLinear\",\"name\":\"sablier\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint128\",\"name\":\"totalAmount\",\"type\":\"uint128\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"cancelable\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"transferable\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"uint40\",\"name\":\"start\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"cliff\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"end\",\"type\":\"uint40\"}],\"internalType\":\"struct LockupLinear.Timestamps\",\"name\":\"timestamps\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"}],\"internalType\":\"struct LockupLinear.Broker\",\"name\":\"broker\",\"type\":\"tuple\"}],\"internalType\":\"struct DecentHats_0_1_0.SablierStreamParams[]\",\"name\":\"sablierParams\",\"type\":\"tuple[]\"}],\"internalType\":\"struct DecentHats_0_1_0.Hat[]\",\"name\":\"hats\",\"type\":\"tuple[]\"}],\"internalType\":\"struct DecentHats_0_1_0.CreateTreeParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"createAndDeclareTree\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/DecentHats_0_1_0.sol\":\"DecentHats_0_1_0\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.7.0 <0.9.0;\\n\\n/// @title Enum - Collection of enums\\n/// @author Richard Meissner - \\ncontract Enum {\\n enum Operation {Call, DelegateCall}\\n}\\n\",\"keccak256\":\"0x473e45b1a5cc47be494b0e123c9127f0c11c1e0992a321ae5a644c0bfdb2c14f\",\"license\":\"LGPL-3.0-only\"},\"@gnosis.pm/zodiac/contracts/interfaces/IAvatar.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\n\\n/// @title Zodiac Avatar - A contract that manages modules that can execute transactions via this contract.\\npragma solidity >=0.7.0 <0.9.0;\\n\\nimport \\\"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\\\";\\n\\ninterface IAvatar {\\n event EnabledModule(address module);\\n event DisabledModule(address module);\\n event ExecutionFromModuleSuccess(address indexed module);\\n event ExecutionFromModuleFailure(address indexed module);\\n\\n /// @dev Enables a module on the avatar.\\n /// @notice Can only be called by the avatar.\\n /// @notice Modules should be stored as a linked list.\\n /// @notice Must emit EnabledModule(address module) if successful.\\n /// @param module Module to be enabled.\\n function enableModule(address module) external;\\n\\n /// @dev Disables a module on the avatar.\\n /// @notice Can only be called by the avatar.\\n /// @notice Must emit DisabledModule(address module) if successful.\\n /// @param prevModule Address that pointed to the module to be removed in the linked list\\n /// @param module Module to be removed.\\n function disableModule(address prevModule, address module) external;\\n\\n /// @dev Allows a Module to execute a transaction.\\n /// @notice Can only be called by an enabled module.\\n /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.\\n /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.\\n /// @param to Destination address of module transaction.\\n /// @param value Ether value of module transaction.\\n /// @param data Data payload of module transaction.\\n /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.\\n function execTransactionFromModule(\\n address to,\\n uint256 value,\\n bytes memory data,\\n Enum.Operation operation\\n ) external returns (bool success);\\n\\n /// @dev Allows a Module to execute a transaction and return data\\n /// @notice Can only be called by an enabled module.\\n /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.\\n /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.\\n /// @param to Destination address of module transaction.\\n /// @param value Ether value of module transaction.\\n /// @param data Data payload of module transaction.\\n /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.\\n function execTransactionFromModuleReturnData(\\n address to,\\n uint256 value,\\n bytes memory data,\\n Enum.Operation operation\\n ) external returns (bool success, bytes memory returnData);\\n\\n /// @dev Returns if an module is enabled\\n /// @return True if the module is enabled\\n function isModuleEnabled(address module) external view returns (bool);\\n\\n /// @dev Returns array of modules.\\n /// @param start Start of the page.\\n /// @param pageSize Maximum number of modules that should be returned.\\n /// @return array Array of modules.\\n /// @return next Start of the next page.\\n function getModulesPaginated(address start, uint256 pageSize)\\n external\\n view\\n returns (address[] memory array, address next);\\n}\\n\",\"keccak256\":\"0xcd5508ffe596eef8fbccfd5fc4f10a34397773547ce64e212d48b5212865ec1f\",\"license\":\"LGPL-3.0-only\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n}\\n\",\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\"},\"contracts/DecentHats_0_1_0.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity =0.8.19;\\n\\nimport {Enum} from \\\"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\\\";\\nimport {IAvatar} from \\\"@gnosis.pm/zodiac/contracts/interfaces/IAvatar.sol\\\";\\nimport {Strings} from \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {IERC6551Registry} from \\\"./interfaces/IERC6551Registry.sol\\\";\\nimport {IHats} from \\\"./interfaces/hats/IHats.sol\\\";\\nimport {ISablierV2LockupLinear} from \\\"./interfaces/sablier/ISablierV2LockupLinear.sol\\\";\\nimport {LockupLinear} from \\\"./interfaces/sablier/LockupLinear.sol\\\";\\n\\ncontract DecentHats_0_1_0 {\\n string public constant NAME = \\\"DecentHats_0_1_0\\\";\\n\\n struct SablierStreamParams {\\n ISablierV2LockupLinear sablier;\\n address sender;\\n uint128 totalAmount;\\n address asset;\\n bool cancelable;\\n bool transferable;\\n LockupLinear.Timestamps timestamps;\\n LockupLinear.Broker broker;\\n }\\n\\n struct Hat {\\n uint32 maxSupply;\\n string details;\\n string imageURI;\\n bool isMutable;\\n address wearer;\\n SablierStreamParams[] sablierParams; // Optional Sablier stream parameters\\n }\\n\\n struct CreateTreeParams {\\n IHats hatsProtocol;\\n address hatsAccountImplementation;\\n IERC6551Registry registry;\\n address keyValuePairs;\\n string topHatDetails;\\n string topHatImageURI;\\n Hat adminHat;\\n Hat[] hats;\\n }\\n\\n function getSalt() internal view returns (bytes32 salt) {\\n uint256 chainId;\\n assembly {\\n chainId := chainid()\\n }\\n\\n bytes memory concatenatedSaltInput = abi.encodePacked(\\n NAME,\\n chainId,\\n address(this)\\n );\\n\\n salt = keccak256(concatenatedSaltInput);\\n }\\n\\n function updateKeyValuePairs(\\n address _keyValuePairs,\\n uint256 topHatId\\n ) internal {\\n string[] memory keys = new string[](1);\\n string[] memory values = new string[](1);\\n keys[0] = \\\"topHatId\\\";\\n values[0] = Strings.toString(topHatId);\\n\\n IAvatar(msg.sender).execTransactionFromModule(\\n _keyValuePairs,\\n 0,\\n abi.encodeWithSignature(\\n \\\"updateValues(string[],string[])\\\",\\n keys,\\n values\\n ),\\n Enum.Operation.Call\\n );\\n }\\n\\n function createHat(\\n IHats _hatsProtocol,\\n uint256 adminHatId,\\n Hat memory _hat,\\n address topHatAccount\\n ) internal returns (uint256) {\\n return\\n _hatsProtocol.createHat(\\n adminHatId,\\n _hat.details,\\n _hat.maxSupply,\\n topHatAccount,\\n topHatAccount,\\n _hat.isMutable,\\n _hat.imageURI\\n );\\n }\\n\\n function createAccount(\\n IERC6551Registry _registry,\\n address _hatsAccountImplementation,\\n bytes32 salt,\\n address protocolAddress,\\n uint256 hatId\\n ) internal returns (address) {\\n return\\n _registry.createAccount(\\n _hatsAccountImplementation,\\n salt,\\n block.chainid,\\n protocolAddress,\\n hatId\\n );\\n }\\n\\n function createTopHatAndAccount(\\n IHats _hatsProtocol,\\n string memory _topHatDetails,\\n string memory _topHatImageURI,\\n IERC6551Registry _registry,\\n address _hatsAccountImplementation,\\n bytes32 salt\\n ) internal returns (uint256 topHatId, address topHatAccount) {\\n topHatId = _hatsProtocol.mintTopHat(\\n address(this),\\n _topHatDetails,\\n _topHatImageURI\\n );\\n\\n topHatAccount = createAccount(\\n _registry,\\n _hatsAccountImplementation,\\n salt,\\n address(_hatsProtocol),\\n topHatId\\n );\\n }\\n\\n function createHatAndAccountAndMintAndStreams(\\n IHats hatsProtocol,\\n uint256 adminHatId,\\n Hat calldata hat,\\n address topHatAccount,\\n IERC6551Registry registry,\\n address hatsAccountImplementation,\\n bytes32 salt\\n ) internal returns (uint256 hatId, address accountAddress) {\\n hatId = createHat(hatsProtocol, adminHatId, hat, topHatAccount);\\n\\n accountAddress = createAccount(\\n registry,\\n hatsAccountImplementation,\\n salt,\\n address(hatsProtocol),\\n hatId\\n );\\n\\n if (hat.wearer != address(0)) {\\n hatsProtocol.mintHat(hatId, hat.wearer);\\n }\\n\\n for (uint256 i = 0; i < hat.sablierParams.length; ) {\\n SablierStreamParams memory sablierParams = hat.sablierParams[i];\\n\\n // Approve tokens for Sablier\\n IAvatar(msg.sender).execTransactionFromModule(\\n sablierParams.asset,\\n 0,\\n abi.encodeWithSignature(\\n \\\"approve(address,uint256)\\\",\\n address(sablierParams.sablier),\\n sablierParams.totalAmount\\n ),\\n Enum.Operation.Call\\n );\\n\\n LockupLinear.CreateWithTimestamps memory params = LockupLinear\\n .CreateWithTimestamps({\\n sender: sablierParams.sender,\\n recipient: accountAddress,\\n totalAmount: sablierParams.totalAmount,\\n asset: IERC20(sablierParams.asset),\\n cancelable: sablierParams.cancelable,\\n transferable: sablierParams.transferable,\\n timestamps: sablierParams.timestamps,\\n broker: sablierParams.broker\\n });\\n\\n // Proxy the Sablier call through IAvatar\\n IAvatar(msg.sender).execTransactionFromModule(\\n address(sablierParams.sablier),\\n 0,\\n abi.encodeWithSignature(\\n \\\"createWithTimestamps((address,address,uint128,address,bool,bool,(uint40,uint40,uint40),(address,uint256)))\\\",\\n params\\n ),\\n Enum.Operation.Call\\n );\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n function createAndDeclareTree(CreateTreeParams calldata params) public {\\n bytes32 salt = getSalt();\\n\\n (uint256 topHatId, address topHatAccount) = createTopHatAndAccount(\\n params.hatsProtocol,\\n params.topHatDetails,\\n params.topHatImageURI,\\n params.registry,\\n params.hatsAccountImplementation,\\n salt\\n );\\n\\n updateKeyValuePairs(params.keyValuePairs, topHatId);\\n\\n (uint256 adminHatId, ) = createHatAndAccountAndMintAndStreams(\\n params.hatsProtocol,\\n topHatId,\\n params.adminHat,\\n topHatAccount,\\n params.registry,\\n params.hatsAccountImplementation,\\n salt\\n );\\n\\n for (uint256 i = 0; i < params.hats.length; ) {\\n createHatAndAccountAndMintAndStreams(\\n params.hatsProtocol,\\n adminHatId,\\n params.hats[i],\\n topHatAccount,\\n params.registry,\\n params.hatsAccountImplementation,\\n salt\\n );\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n params.hatsProtocol.transferHat(topHatId, address(this), msg.sender);\\n }\\n}\\n\",\"keccak256\":\"0xdc0d2b3c556d675f26152895a17e1fb76c91d1a85b2689cf435fb3666381ac41\",\"license\":\"MIT\"},\"contracts/interfaces/IERC6551Registry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IERC6551Registry {\\n /**\\n * @dev Creates a token bound account for a non-fungible token.\\n *\\n * If account has already been created, returns the account address without calling create2.\\n *\\n * Emits ERC6551AccountCreated event.\\n *\\n * @return account The address of the token bound account\\n */\\n function createAccount(\\n address implementation,\\n bytes32 salt,\\n uint256 chainId,\\n address tokenContract,\\n uint256 tokenId\\n ) external returns (address account);\\n}\\n\",\"keccak256\":\"0x64c52de8a8e68398e61dd8b42dda8e9af8cf6abf93bb85629c322440991ea568\",\"license\":\"MIT\"},\"contracts/interfaces/hats/IHats.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0\\n// Copyright (C) 2023 Haberdasher Labs\\n//\\n// This program is free software: you can redistribute it and/or modify\\n// it under the terms of the GNU Affero General Public License as published by\\n// the Free Software Foundation, either version 3 of the License, or\\n// (at your option) any later version.\\n//\\n// This program is distributed in the hope that it will be useful,\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\\n// GNU Affero General Public License for more details.\\n//\\n// You should have received a copy of the GNU Affero General Public License\\n// along with this program. If not, see .\\n\\npragma solidity >=0.8.13;\\n\\ninterface IHats {\\n function mintTopHat(\\n address _target,\\n string memory _details,\\n string memory _imageURI\\n ) external returns (uint256 topHatId);\\n\\n function createHat(\\n uint256 _admin,\\n string calldata _details,\\n uint32 _maxSupply,\\n address _eligibility,\\n address _toggle,\\n bool _mutable,\\n string calldata _imageURI\\n ) external returns (uint256 newHatId);\\n\\n function mintHat(\\n uint256 _hatId,\\n address _wearer\\n ) external returns (bool success);\\n\\n function transferHat(uint256 _hatId, address _from, address _to) external;\\n}\\n\",\"keccak256\":\"0x8e35022f5c0fcf0059033abec78ec890f0cf3bbac09d6d24051cff9679239511\",\"license\":\"AGPL-3.0\"},\"contracts/interfaces/sablier/ISablierV2LockupLinear.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {LockupLinear} from \\\"./LockupLinear.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface ISablierV2LockupLinear {\\n function createWithTimestamps(\\n LockupLinear.CreateWithTimestamps calldata params\\n ) external returns (uint256 streamId);\\n}\\n\",\"keccak256\":\"0xf4899637eb2e6c76c35e2d201e56e162a50e6bc7b5b9156e00866f0703ad07ca\",\"license\":\"MIT\"},\"contracts/interfaces/sablier/LockupLinear.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LockupLinear {\\n struct CreateWithTimestamps {\\n address sender;\\n address recipient;\\n uint128 totalAmount;\\n IERC20 asset;\\n bool cancelable;\\n bool transferable;\\n Timestamps timestamps;\\n Broker broker;\\n }\\n\\n struct Timestamps {\\n uint40 start;\\n uint40 cliff;\\n uint40 end;\\n }\\n\\n struct Broker {\\n address account;\\n uint256 fee;\\n }\\n}\\n\",\"keccak256\":\"0x497fdb52b5e1a5a7e0711a9f7d5fb036eb668ccb92ea908ee088f56ee08a4ce8\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50611477806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80638c5f591a1461003b578063a3f4df7e14610050575b600080fd5b61004e610049366004610ac2565b610095565b005b61007f6040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b81525081565b60405161008c9190610b54565b60405180910390f35b600061009f6102cd565b905060008061015e6100b46020860186610b7f565b6100c16080870187610b9c565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506101039250505060a0880188610b9c565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610148925050506060890160408a01610b7f565b61015860408a0160208b01610b7f565b88610331565b909250905061017c6101766080860160608701610b7f565b836103c3565b60006101c361018e6020870187610b7f565b8461019c60c0890189610bf9565b856101ad60608b0160408c01610b7f565b6101bd60408c0160208d01610b7f565b8a610543565b50905060005b6101d660e0870187610c19565b9050811015610250576102466101ef6020880188610b7f565b836101fd60e08a018a610c19565b8581811061020d5761020d610c62565b905060200281019061021f9190610bf9565b8661023060608c0160408d01610b7f565b61024060408d0160208e01610b7f565b8b610543565b50506001016101c9565b5061025e6020860186610b7f565b6040516329287c1b60e21b8152600481018590523060248201523360448201526001600160a01b03919091169063a4a1f06c90606401600060405180830381600087803b1580156102ae57600080fd5b505af11580156102c2573d6000803e3d6000fd5b505050505050505050565b60008046905060006040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b815250823060405160200161031293929190610c78565b60408051601f1981840301815291905280516020909101209392505050565b600080876001600160a01b0316631a64dfad3089896040518463ffffffff1660e01b815260040161036493929190610cb1565b6020604051808303816000875af1158015610383573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a79190610ce7565b91506103b68585858b86610892565b9050965096945050505050565b604080516001808252818301909252600091816020015b60608152602001906001900390816103da57505060408051600180825281830190925291925060009190602082015b6060815260200190600190039081610409579050509050604051806040016040528060088152602001671d1bdc12185d125960c21b8152508260008151811061045457610454610c62565b602002602001018190525061046883610928565b8160008151811061047b5761047b610c62565b6020026020010181905250336001600160a01b031663468721a785600085856040516024016104ab929190610d6b565b60408051601f198184030181529181526020820180516001600160e01b031663579374b960e11b1790525160e085901b6001600160e01b03191681526104f993929190600090600401610d90565b6020604051808303816000875af1158015610518573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053c9190610df4565b5050505050565b60008061055a89896105548a61113b565b89610a30565b91506105698585858c86610892565b9050600061057d60a0890160808a01610b7f565b6001600160a01b03161461061d576001600160a01b03891663641f776e836105ab60a08b0160808c01610b7f565b6040516001600160e01b031960e085901b16815260048101929092526001600160a01b031660248201526044016020604051808303816000875af11580156105f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061b9190610df4565b505b60005b61062d60a08901896111ff565b905081101561088557600061064560a08a018a6111ff565b8381811061065557610655610c62565b9050610160020180360381019061066c9190611248565b6060810151815160408084015190516001600160a01b0390921660248301526001600160801b03166044820152919250339163468721a7919060009060640160408051601f198184030181529181526020820180516001600160e01b031663095ea7b360e01b1790525160e085901b6001600160e01b03191681526106f993929190600090600401610d90565b6020604051808303816000875af1158015610718573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073c9190610df4565b50600060405180610100016040528083602001516001600160a01b03168152602001856001600160a01b0316815260200183604001516001600160801b0316815260200183606001516001600160a01b031681526020018360800151151581526020018360a00151151581526020018360c0015181526020018360e001518152509050336001600160a01b031663468721a783600001516000846040516024016107e69190611265565b60408051601f198184030181529181526020820180516001600160e01b03166353b1572760e01b1790525160e085901b6001600160e01b031916815261083493929190600090600401610d90565b6020604051808303816000875af1158015610853573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108779190610df4565b508260010192505050610620565b5097509795505050505050565b604051638a54c52f60e01b81526001600160a01b0385811660048301526024820185905246604483015283811660648301526084820183905260009190871690638a54c52f9060a4016020604051808303816000875af11580156108fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091e9190611327565b9695505050505050565b60608160000361094f5750506040805180820190915260018152600360fc1b602082015290565b8160005b811561097957806109638161135a565b91506109729050600a83611389565b9150610953565b6000816001600160401b0381111561099357610993610d00565b6040519080825280601f01601f1916602001820160405280156109bd576020820181803683370190505b5090505b8415610a28576109d260018361139d565b91506109df600a866113b6565b6109ea9060306113ca565b60f81b8183815181106109ff576109ff610c62565b60200101906001600160f81b031916908160001a905350610a21600a86611389565b94506109c1565b949350505050565b6020820151825160608401516040808601519051635829492f60e11b81526000946001600160a01b038a169463b052925e94610a76948b948a92839290916004016113dd565b6020604051808303816000875af1158015610a95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab99190610ce7565b95945050505050565b600060208284031215610ad457600080fd5b81356001600160401b03811115610aea57600080fd5b82016101008185031215610afd57600080fd5b9392505050565b60005b83811015610b1f578181015183820152602001610b07565b50506000910152565b60008151808452610b40816020860160208601610b04565b601f01601f19169290920160200192915050565b602081526000610afd6020830184610b28565b6001600160a01b0381168114610b7c57600080fd5b50565b600060208284031215610b9157600080fd5b8135610afd81610b67565b6000808335601e19843603018112610bb357600080fd5b8301803591506001600160401b03821115610bcd57600080fd5b602001915036819003821315610be257600080fd5b9250929050565b8035610bf481610b67565b919050565b6000823560be19833603018112610c0f57600080fd5b9190910192915050565b6000808335601e19843603018112610c3057600080fd5b8301803591506001600160401b03821115610c4a57600080fd5b6020019150600581901b3603821315610be257600080fd5b634e487b7160e01b600052603260045260246000fd5b60008451610c8a818460208901610b04565b919091019283525060601b6bffffffffffffffffffffffff19166020820152603401919050565b6001600160a01b0384168152606060208201819052600090610cd590830185610b28565b828103604084015261091e8185610b28565b600060208284031215610cf957600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b600081518084526020808501808196508360051b8101915082860160005b85811015610d5e578284038952610d4c848351610b28565b98850198935090840190600101610d34565b5091979650505050505050565b604081526000610d7e6040830185610d16565b8281036020840152610ab98185610d16565b60018060a01b0385168152836020820152608060408201526000610db76080830185610b28565b905060028310610dd757634e487b7160e01b600052602160045260246000fd5b82606083015295945050505050565b8015158114610b7c57600080fd5b600060208284031215610e0657600080fd5b8151610afd81610de6565b60405160c081016001600160401b0381118282101715610e3357610e33610d00565b60405290565b604051601f8201601f191681016001600160401b0381118282101715610e6157610e61610d00565b604052919050565b803563ffffffff81168114610bf457600080fd5b600082601f830112610e8e57600080fd5b81356001600160401b03811115610ea757610ea7610d00565b610eba601f8201601f1916602001610e39565b818152846020838601011115610ecf57600080fd5b816020850160208301376000918101602001919091529392505050565b8035610bf481610de6565b80356001600160801b0381168114610bf457600080fd5b803564ffffffffff81168114610bf457600080fd5b600060608284031215610f3557600080fd5b604051606081018181106001600160401b0382111715610f5757610f57610d00565b604052905080610f6683610f0e565b8152610f7460208401610f0e565b6020820152610f8560408401610f0e565b60408201525092915050565b600060408284031215610fa357600080fd5b604051604081018181106001600160401b0382111715610fc557610fc5610d00565b6040529050808235610fd681610b67565b8152602092830135920191909152919050565b60006101608284031215610ffc57600080fd5b60405161010081018181106001600160401b038211171561101f5761101f610d00565b60405290508061102e83610be9565b815261103c60208401610be9565b602082015261104d60408401610ef7565b604082015261105e60608401610be9565b606082015261106f60808401610eec565b608082015261108060a08401610eec565b60a08201526110928460c08501610f23565b60c08201526110a5846101208501610f91565b60e08201525092915050565b600082601f8301126110c257600080fd5b813560206001600160401b038211156110dd576110dd610d00565b6110eb818360051b01610e39565b828152610160928302850182019282820191908785111561110b57600080fd5b8387015b8581101561112e576111218982610fe9565b845292840192810161110f565b5090979650505050505050565b600060c0823603121561114d57600080fd5b611155610e11565b61115e83610e69565b815260208301356001600160401b038082111561117a57600080fd5b61118636838701610e7d565b6020840152604085013591508082111561119f57600080fd5b6111ab36838701610e7d565b60408401526111bc60608601610eec565b60608401526111cd60808601610be9565b608084015260a08501359150808211156111e657600080fd5b506111f3368286016110b1565b60a08301525092915050565b6000808335601e1984360301811261121657600080fd5b8301803591506001600160401b0382111561123057600080fd5b602001915061016081023603821315610be257600080fd5b6000610160828403121561125b57600080fd5b610afd8383610fe9565b81516001600160a01b0390811682526020808401518216908301526040808401516001600160801b031690830152606080840151909116908201526080808301516101608301916112b99084018215159052565b5060a08301516112cd60a084018215159052565b5060c083015161130060c0840182805164ffffffffff908116835260208083015182169084015260409182015116910152565b5060e0929092015180516001600160a01b0316610120830152602001516101409091015290565b60006020828403121561133957600080fd5b8151610afd81610b67565b634e487b7160e01b600052601160045260246000fd5b60006001820161136c5761136c611344565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261139857611398611373565b500490565b818103818111156113b0576113b0611344565b92915050565b6000826113c5576113c5611373565b500690565b808201808211156113b0576113b0611344565b87815260e0602082015260006113f660e0830189610b28565b63ffffffff881660408401526001600160a01b0387811660608501528616608084015284151560a084015282810360c08401526114338185610b28565b9a995050505050505050505056fea2646970667358221220d17954ba81bca52da6ca1f1cf74a0e04f2ce3c50651d1d806611eb18ab0d551e64736f6c63430008130033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80638c5f591a1461003b578063a3f4df7e14610050575b600080fd5b61004e610049366004610ac2565b610095565b005b61007f6040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b81525081565b60405161008c9190610b54565b60405180910390f35b600061009f6102cd565b905060008061015e6100b46020860186610b7f565b6100c16080870187610b9c565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506101039250505060a0880188610b9c565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610148925050506060890160408a01610b7f565b61015860408a0160208b01610b7f565b88610331565b909250905061017c6101766080860160608701610b7f565b836103c3565b60006101c361018e6020870187610b7f565b8461019c60c0890189610bf9565b856101ad60608b0160408c01610b7f565b6101bd60408c0160208d01610b7f565b8a610543565b50905060005b6101d660e0870187610c19565b9050811015610250576102466101ef6020880188610b7f565b836101fd60e08a018a610c19565b8581811061020d5761020d610c62565b905060200281019061021f9190610bf9565b8661023060608c0160408d01610b7f565b61024060408d0160208e01610b7f565b8b610543565b50506001016101c9565b5061025e6020860186610b7f565b6040516329287c1b60e21b8152600481018590523060248201523360448201526001600160a01b03919091169063a4a1f06c90606401600060405180830381600087803b1580156102ae57600080fd5b505af11580156102c2573d6000803e3d6000fd5b505050505050505050565b60008046905060006040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b815250823060405160200161031293929190610c78565b60408051601f1981840301815291905280516020909101209392505050565b600080876001600160a01b0316631a64dfad3089896040518463ffffffff1660e01b815260040161036493929190610cb1565b6020604051808303816000875af1158015610383573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a79190610ce7565b91506103b68585858b86610892565b9050965096945050505050565b604080516001808252818301909252600091816020015b60608152602001906001900390816103da57505060408051600180825281830190925291925060009190602082015b6060815260200190600190039081610409579050509050604051806040016040528060088152602001671d1bdc12185d125960c21b8152508260008151811061045457610454610c62565b602002602001018190525061046883610928565b8160008151811061047b5761047b610c62565b6020026020010181905250336001600160a01b031663468721a785600085856040516024016104ab929190610d6b565b60408051601f198184030181529181526020820180516001600160e01b031663579374b960e11b1790525160e085901b6001600160e01b03191681526104f993929190600090600401610d90565b6020604051808303816000875af1158015610518573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053c9190610df4565b5050505050565b60008061055a89896105548a61113b565b89610a30565b91506105698585858c86610892565b9050600061057d60a0890160808a01610b7f565b6001600160a01b03161461061d576001600160a01b03891663641f776e836105ab60a08b0160808c01610b7f565b6040516001600160e01b031960e085901b16815260048101929092526001600160a01b031660248201526044016020604051808303816000875af11580156105f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061b9190610df4565b505b60005b61062d60a08901896111ff565b905081101561088557600061064560a08a018a6111ff565b8381811061065557610655610c62565b9050610160020180360381019061066c9190611248565b6060810151815160408084015190516001600160a01b0390921660248301526001600160801b03166044820152919250339163468721a7919060009060640160408051601f198184030181529181526020820180516001600160e01b031663095ea7b360e01b1790525160e085901b6001600160e01b03191681526106f993929190600090600401610d90565b6020604051808303816000875af1158015610718573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073c9190610df4565b50600060405180610100016040528083602001516001600160a01b03168152602001856001600160a01b0316815260200183604001516001600160801b0316815260200183606001516001600160a01b031681526020018360800151151581526020018360a00151151581526020018360c0015181526020018360e001518152509050336001600160a01b031663468721a783600001516000846040516024016107e69190611265565b60408051601f198184030181529181526020820180516001600160e01b03166353b1572760e01b1790525160e085901b6001600160e01b031916815261083493929190600090600401610d90565b6020604051808303816000875af1158015610853573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108779190610df4565b508260010192505050610620565b5097509795505050505050565b604051638a54c52f60e01b81526001600160a01b0385811660048301526024820185905246604483015283811660648301526084820183905260009190871690638a54c52f9060a4016020604051808303816000875af11580156108fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091e9190611327565b9695505050505050565b60608160000361094f5750506040805180820190915260018152600360fc1b602082015290565b8160005b811561097957806109638161135a565b91506109729050600a83611389565b9150610953565b6000816001600160401b0381111561099357610993610d00565b6040519080825280601f01601f1916602001820160405280156109bd576020820181803683370190505b5090505b8415610a28576109d260018361139d565b91506109df600a866113b6565b6109ea9060306113ca565b60f81b8183815181106109ff576109ff610c62565b60200101906001600160f81b031916908160001a905350610a21600a86611389565b94506109c1565b949350505050565b6020820151825160608401516040808601519051635829492f60e11b81526000946001600160a01b038a169463b052925e94610a76948b948a92839290916004016113dd565b6020604051808303816000875af1158015610a95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab99190610ce7565b95945050505050565b600060208284031215610ad457600080fd5b81356001600160401b03811115610aea57600080fd5b82016101008185031215610afd57600080fd5b9392505050565b60005b83811015610b1f578181015183820152602001610b07565b50506000910152565b60008151808452610b40816020860160208601610b04565b601f01601f19169290920160200192915050565b602081526000610afd6020830184610b28565b6001600160a01b0381168114610b7c57600080fd5b50565b600060208284031215610b9157600080fd5b8135610afd81610b67565b6000808335601e19843603018112610bb357600080fd5b8301803591506001600160401b03821115610bcd57600080fd5b602001915036819003821315610be257600080fd5b9250929050565b8035610bf481610b67565b919050565b6000823560be19833603018112610c0f57600080fd5b9190910192915050565b6000808335601e19843603018112610c3057600080fd5b8301803591506001600160401b03821115610c4a57600080fd5b6020019150600581901b3603821315610be257600080fd5b634e487b7160e01b600052603260045260246000fd5b60008451610c8a818460208901610b04565b919091019283525060601b6bffffffffffffffffffffffff19166020820152603401919050565b6001600160a01b0384168152606060208201819052600090610cd590830185610b28565b828103604084015261091e8185610b28565b600060208284031215610cf957600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b600081518084526020808501808196508360051b8101915082860160005b85811015610d5e578284038952610d4c848351610b28565b98850198935090840190600101610d34565b5091979650505050505050565b604081526000610d7e6040830185610d16565b8281036020840152610ab98185610d16565b60018060a01b0385168152836020820152608060408201526000610db76080830185610b28565b905060028310610dd757634e487b7160e01b600052602160045260246000fd5b82606083015295945050505050565b8015158114610b7c57600080fd5b600060208284031215610e0657600080fd5b8151610afd81610de6565b60405160c081016001600160401b0381118282101715610e3357610e33610d00565b60405290565b604051601f8201601f191681016001600160401b0381118282101715610e6157610e61610d00565b604052919050565b803563ffffffff81168114610bf457600080fd5b600082601f830112610e8e57600080fd5b81356001600160401b03811115610ea757610ea7610d00565b610eba601f8201601f1916602001610e39565b818152846020838601011115610ecf57600080fd5b816020850160208301376000918101602001919091529392505050565b8035610bf481610de6565b80356001600160801b0381168114610bf457600080fd5b803564ffffffffff81168114610bf457600080fd5b600060608284031215610f3557600080fd5b604051606081018181106001600160401b0382111715610f5757610f57610d00565b604052905080610f6683610f0e565b8152610f7460208401610f0e565b6020820152610f8560408401610f0e565b60408201525092915050565b600060408284031215610fa357600080fd5b604051604081018181106001600160401b0382111715610fc557610fc5610d00565b6040529050808235610fd681610b67565b8152602092830135920191909152919050565b60006101608284031215610ffc57600080fd5b60405161010081018181106001600160401b038211171561101f5761101f610d00565b60405290508061102e83610be9565b815261103c60208401610be9565b602082015261104d60408401610ef7565b604082015261105e60608401610be9565b606082015261106f60808401610eec565b608082015261108060a08401610eec565b60a08201526110928460c08501610f23565b60c08201526110a5846101208501610f91565b60e08201525092915050565b600082601f8301126110c257600080fd5b813560206001600160401b038211156110dd576110dd610d00565b6110eb818360051b01610e39565b828152610160928302850182019282820191908785111561110b57600080fd5b8387015b8581101561112e576111218982610fe9565b845292840192810161110f565b5090979650505050505050565b600060c0823603121561114d57600080fd5b611155610e11565b61115e83610e69565b815260208301356001600160401b038082111561117a57600080fd5b61118636838701610e7d565b6020840152604085013591508082111561119f57600080fd5b6111ab36838701610e7d565b60408401526111bc60608601610eec565b60608401526111cd60808601610be9565b608084015260a08501359150808211156111e657600080fd5b506111f3368286016110b1565b60a08301525092915050565b6000808335601e1984360301811261121657600080fd5b8301803591506001600160401b0382111561123057600080fd5b602001915061016081023603821315610be257600080fd5b6000610160828403121561125b57600080fd5b610afd8383610fe9565b81516001600160a01b0390811682526020808401518216908301526040808401516001600160801b031690830152606080840151909116908201526080808301516101608301916112b99084018215159052565b5060a08301516112cd60a084018215159052565b5060c083015161130060c0840182805164ffffffffff908116835260208083015182169084015260409182015116910152565b5060e0929092015180516001600160a01b0316610120830152602001516101409091015290565b60006020828403121561133957600080fd5b8151610afd81610b67565b634e487b7160e01b600052601160045260246000fd5b60006001820161136c5761136c611344565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261139857611398611373565b500490565b818103818111156113b0576113b0611344565b92915050565b6000826113c5576113c5611373565b500690565b808201808211156113b0576113b0611344565b87815260e0602082015260006113f660e0830189610b28565b63ffffffff881660408401526001600160a01b0387811660608501528616608084015284151560a084015282810360c08401526114338185610b28565b9a995050505050505050505056fea2646970667358221220d17954ba81bca52da6ca1f1cf74a0e04f2ce3c50651d1d806611eb18ab0d551e64736f6c63430008130033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/base/solcInputs/512807b5d71481c693c202ae23158904.json b/deployments/base/solcInputs/512807b5d71481c693c202ae23158904.json new file mode 100644 index 00000000..0d0d55c8 --- /dev/null +++ b/deployments/base/solcInputs/512807b5d71481c693c202ae23158904.json @@ -0,0 +1,59 @@ +{ + "language": "Solidity", + "sources": { + "@gnosis.pm/safe-contracts/contracts/common/Enum.sol": { + "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.0 <0.9.0;\n\n/// @title Enum - Collection of enums\n/// @author Richard Meissner - \ncontract Enum {\n enum Operation {Call, DelegateCall}\n}\n" + }, + "@gnosis.pm/zodiac/contracts/interfaces/IAvatar.sol": { + "content": "// SPDX-License-Identifier: LGPL-3.0-only\n\n/// @title Zodiac Avatar - A contract that manages modules that can execute transactions via this contract.\npragma solidity >=0.7.0 <0.9.0;\n\nimport \"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\";\n\ninterface IAvatar {\n event EnabledModule(address module);\n event DisabledModule(address module);\n event ExecutionFromModuleSuccess(address indexed module);\n event ExecutionFromModuleFailure(address indexed module);\n\n /// @dev Enables a module on the avatar.\n /// @notice Can only be called by the avatar.\n /// @notice Modules should be stored as a linked list.\n /// @notice Must emit EnabledModule(address module) if successful.\n /// @param module Module to be enabled.\n function enableModule(address module) external;\n\n /// @dev Disables a module on the avatar.\n /// @notice Can only be called by the avatar.\n /// @notice Must emit DisabledModule(address module) if successful.\n /// @param prevModule Address that pointed to the module to be removed in the linked list\n /// @param module Module to be removed.\n function disableModule(address prevModule, address module) external;\n\n /// @dev Allows a Module to execute a transaction.\n /// @notice Can only be called by an enabled module.\n /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.\n /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.\n /// @param to Destination address of module transaction.\n /// @param value Ether value of module transaction.\n /// @param data Data payload of module transaction.\n /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.\n function execTransactionFromModule(\n address to,\n uint256 value,\n bytes memory data,\n Enum.Operation operation\n ) external returns (bool success);\n\n /// @dev Allows a Module to execute a transaction and return data\n /// @notice Can only be called by an enabled module.\n /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.\n /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.\n /// @param to Destination address of module transaction.\n /// @param value Ether value of module transaction.\n /// @param data Data payload of module transaction.\n /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.\n function execTransactionFromModuleReturnData(\n address to,\n uint256 value,\n bytes memory data,\n Enum.Operation operation\n ) external returns (bool success, bytes memory returnData);\n\n /// @dev Returns if an module is enabled\n /// @return True if the module is enabled\n function isModuleEnabled(address module) external view returns (bool);\n\n /// @dev Returns array of modules.\n /// @param start Start of the page.\n /// @param pageSize Maximum number of modules that should be returned.\n /// @return array Array of modules.\n /// @return next Start of the next page.\n function getModulesPaginated(address start, uint256 pageSize)\n external\n view\n returns (address[] memory array, address next);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp >>= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n" + }, + "contracts/DecentHats_0_1_0.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity =0.8.19;\n\nimport {Enum} from \"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\";\nimport {IAvatar} from \"@gnosis.pm/zodiac/contracts/interfaces/IAvatar.sol\";\nimport {Strings} from \"@openzeppelin/contracts/utils/Strings.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {IERC6551Registry} from \"./interfaces/IERC6551Registry.sol\";\nimport {IHats} from \"./interfaces/hats/IHats.sol\";\nimport {ISablierV2LockupLinear} from \"./interfaces/sablier/ISablierV2LockupLinear.sol\";\nimport {LockupLinear} from \"./interfaces/sablier/LockupLinear.sol\";\n\ncontract DecentHats_0_1_0 {\n string public constant NAME = \"DecentHats_0_1_0\";\n\n struct SablierStreamParams {\n ISablierV2LockupLinear sablier;\n address sender;\n uint128 totalAmount;\n address asset;\n bool cancelable;\n bool transferable;\n LockupLinear.Timestamps timestamps;\n LockupLinear.Broker broker;\n }\n\n struct Hat {\n uint32 maxSupply;\n string details;\n string imageURI;\n bool isMutable;\n address wearer;\n SablierStreamParams[] sablierParams; // Optional Sablier stream parameters\n }\n\n struct CreateTreeParams {\n IHats hatsProtocol;\n address hatsAccountImplementation;\n IERC6551Registry registry;\n address keyValuePairs;\n string topHatDetails;\n string topHatImageURI;\n Hat adminHat;\n Hat[] hats;\n }\n\n function getSalt() internal view returns (bytes32 salt) {\n uint256 chainId;\n assembly {\n chainId := chainid()\n }\n\n bytes memory concatenatedSaltInput = abi.encodePacked(\n NAME,\n chainId,\n address(this)\n );\n\n salt = keccak256(concatenatedSaltInput);\n }\n\n function updateKeyValuePairs(\n address _keyValuePairs,\n uint256 topHatId\n ) internal {\n string[] memory keys = new string[](1);\n string[] memory values = new string[](1);\n keys[0] = \"topHatId\";\n values[0] = Strings.toString(topHatId);\n\n IAvatar(msg.sender).execTransactionFromModule(\n _keyValuePairs,\n 0,\n abi.encodeWithSignature(\n \"updateValues(string[],string[])\",\n keys,\n values\n ),\n Enum.Operation.Call\n );\n }\n\n function createHat(\n IHats _hatsProtocol,\n uint256 adminHatId,\n Hat memory _hat,\n address topHatAccount\n ) internal returns (uint256) {\n return\n _hatsProtocol.createHat(\n adminHatId,\n _hat.details,\n _hat.maxSupply,\n topHatAccount,\n topHatAccount,\n _hat.isMutable,\n _hat.imageURI\n );\n }\n\n function createAccount(\n IERC6551Registry _registry,\n address _hatsAccountImplementation,\n bytes32 salt,\n address protocolAddress,\n uint256 hatId\n ) internal returns (address) {\n return\n _registry.createAccount(\n _hatsAccountImplementation,\n salt,\n block.chainid,\n protocolAddress,\n hatId\n );\n }\n\n function createTopHatAndAccount(\n IHats _hatsProtocol,\n string memory _topHatDetails,\n string memory _topHatImageURI,\n IERC6551Registry _registry,\n address _hatsAccountImplementation,\n bytes32 salt\n ) internal returns (uint256 topHatId, address topHatAccount) {\n topHatId = _hatsProtocol.mintTopHat(\n address(this),\n _topHatDetails,\n _topHatImageURI\n );\n\n topHatAccount = createAccount(\n _registry,\n _hatsAccountImplementation,\n salt,\n address(_hatsProtocol),\n topHatId\n );\n }\n\n function createHatAndAccountAndMintAndStreams(\n IHats hatsProtocol,\n uint256 adminHatId,\n Hat calldata hat,\n address topHatAccount,\n IERC6551Registry registry,\n address hatsAccountImplementation,\n bytes32 salt\n ) internal returns (uint256 hatId, address accountAddress) {\n hatId = createHat(hatsProtocol, adminHatId, hat, topHatAccount);\n\n accountAddress = createAccount(\n registry,\n hatsAccountImplementation,\n salt,\n address(hatsProtocol),\n hatId\n );\n\n if (hat.wearer != address(0)) {\n hatsProtocol.mintHat(hatId, hat.wearer);\n }\n\n for (uint256 i = 0; i < hat.sablierParams.length; ) {\n SablierStreamParams memory sablierParams = hat.sablierParams[i];\n\n // Approve tokens for Sablier\n IAvatar(msg.sender).execTransactionFromModule(\n sablierParams.asset,\n 0,\n abi.encodeWithSignature(\n \"approve(address,uint256)\",\n address(sablierParams.sablier),\n sablierParams.totalAmount\n ),\n Enum.Operation.Call\n );\n\n LockupLinear.CreateWithTimestamps memory params = LockupLinear\n .CreateWithTimestamps({\n sender: sablierParams.sender,\n recipient: accountAddress,\n totalAmount: sablierParams.totalAmount,\n asset: IERC20(sablierParams.asset),\n cancelable: sablierParams.cancelable,\n transferable: sablierParams.transferable,\n timestamps: sablierParams.timestamps,\n broker: sablierParams.broker\n });\n\n // Proxy the Sablier call through IAvatar\n IAvatar(msg.sender).execTransactionFromModule(\n address(sablierParams.sablier),\n 0,\n abi.encodeWithSignature(\n \"createWithTimestamps((address,address,uint128,address,bool,bool,(uint40,uint40,uint40),(address,uint256)))\",\n params\n ),\n Enum.Operation.Call\n );\n\n unchecked {\n ++i;\n }\n }\n }\n\n function createAndDeclareTree(CreateTreeParams calldata params) public {\n bytes32 salt = getSalt();\n\n (uint256 topHatId, address topHatAccount) = createTopHatAndAccount(\n params.hatsProtocol,\n params.topHatDetails,\n params.topHatImageURI,\n params.registry,\n params.hatsAccountImplementation,\n salt\n );\n\n updateKeyValuePairs(params.keyValuePairs, topHatId);\n\n (uint256 adminHatId, ) = createHatAndAccountAndMintAndStreams(\n params.hatsProtocol,\n topHatId,\n params.adminHat,\n topHatAccount,\n params.registry,\n params.hatsAccountImplementation,\n salt\n );\n\n for (uint256 i = 0; i < params.hats.length; ) {\n createHatAndAccountAndMintAndStreams(\n params.hatsProtocol,\n adminHatId,\n params.hats[i],\n topHatAccount,\n params.registry,\n params.hatsAccountImplementation,\n salt\n );\n\n unchecked {\n ++i;\n }\n }\n\n params.hatsProtocol.transferHat(topHatId, address(this), msg.sender);\n }\n}\n" + }, + "contracts/interfaces/hats/IHats.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0\n// Copyright (C) 2023 Haberdasher Labs\n//\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU Affero General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU Affero General Public License for more details.\n//\n// You should have received a copy of the GNU Affero General Public License\n// along with this program. If not, see .\n\npragma solidity >=0.8.13;\n\ninterface IHats {\n function mintTopHat(\n address _target,\n string memory _details,\n string memory _imageURI\n ) external returns (uint256 topHatId);\n\n function createHat(\n uint256 _admin,\n string calldata _details,\n uint32 _maxSupply,\n address _eligibility,\n address _toggle,\n bool _mutable,\n string calldata _imageURI\n ) external returns (uint256 newHatId);\n\n function mintHat(\n uint256 _hatId,\n address _wearer\n ) external returns (bool success);\n\n function transferHat(uint256 _hatId, address _from, address _to) external;\n}\n" + }, + "contracts/interfaces/IERC6551Registry.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\ninterface IERC6551Registry {\n /**\n * @dev Creates a token bound account for a non-fungible token.\n *\n * If account has already been created, returns the account address without calling create2.\n *\n * Emits ERC6551AccountCreated event.\n *\n * @return account The address of the token bound account\n */\n function createAccount(\n address implementation,\n bytes32 salt,\n uint256 chainId,\n address tokenContract,\n uint256 tokenId\n ) external returns (address account);\n}\n" + }, + "contracts/interfaces/sablier/ISablierV2LockupLinear.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {LockupLinear} from \"./LockupLinear.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface ISablierV2LockupLinear {\n function createWithTimestamps(\n LockupLinear.CreateWithTimestamps calldata params\n ) external returns (uint256 streamId);\n}\n" + }, + "contracts/interfaces/sablier/LockupLinear.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LockupLinear {\n struct CreateWithTimestamps {\n address sender;\n address recipient;\n uint128 totalAmount;\n IERC20 asset;\n bool cancelable;\n bool transferable;\n Timestamps timestamps;\n Broker broker;\n }\n\n struct Timestamps {\n uint40 start;\n uint40 cliff;\n uint40 end;\n }\n\n struct Broker {\n address account;\n uint256 fee;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/deployments/mainnet/DecentHats_0_1_0.json b/deployments/mainnet/DecentHats_0_1_0.json index eb01b38b..e702d8d6 100644 --- a/deployments/mainnet/DecentHats_0_1_0.json +++ b/deployments/mainnet/DecentHats_0_1_0.json @@ -1,5 +1,5 @@ { - "address": "0x00b089E0A6fdE24cf8978994c7BcD24fc1D79825", + "address": "0x2A8Bf5E47FDcceA8Ab31A995C25198996D5ac514", "abi": [ { "inputs": [], @@ -74,6 +74,82 @@ "internalType": "address", "name": "wearer", "type": "address" + }, + { + "components": [ + { + "internalType": "contract ISablierV2LockupLinear", + "name": "sablier", + "type": "address" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint128", + "name": "totalAmount", + "type": "uint128" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "bool", + "name": "cancelable", + "type": "bool" + }, + { + "internalType": "bool", + "name": "transferable", + "type": "bool" + }, + { + "components": [ + { + "internalType": "uint40", + "name": "start", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "cliff", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "end", + "type": "uint40" + } + ], + "internalType": "struct LockupLinear.Timestamps", + "name": "timestamps", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "fee", + "type": "uint256" + } + ], + "internalType": "struct LockupLinear.Broker", + "name": "broker", + "type": "tuple" + } + ], + "internalType": "struct DecentHats_0_1_0.SablierStreamParams[]", + "name": "sablierParams", + "type": "tuple[]" } ], "internalType": "struct DecentHats_0_1_0.Hat", @@ -106,6 +182,82 @@ "internalType": "address", "name": "wearer", "type": "address" + }, + { + "components": [ + { + "internalType": "contract ISablierV2LockupLinear", + "name": "sablier", + "type": "address" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint128", + "name": "totalAmount", + "type": "uint128" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "bool", + "name": "cancelable", + "type": "bool" + }, + { + "internalType": "bool", + "name": "transferable", + "type": "bool" + }, + { + "components": [ + { + "internalType": "uint40", + "name": "start", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "cliff", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "end", + "type": "uint40" + } + ], + "internalType": "struct LockupLinear.Timestamps", + "name": "timestamps", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "fee", + "type": "uint256" + } + ], + "internalType": "struct LockupLinear.Broker", + "name": "broker", + "type": "tuple" + } + ], + "internalType": "struct DecentHats_0_1_0.SablierStreamParams[]", + "name": "sablierParams", + "type": "tuple[]" } ], "internalType": "struct DecentHats_0_1_0.Hat[]", @@ -124,28 +276,28 @@ "type": "function" } ], - "transactionHash": "0xfbda17788d3c9cabb36554434e15de11550808248c0ce91e46d99562d54e5fa9", + "transactionHash": "0xd64b5a21c53cd3281ea5a9384ffd4ecb357e8bb523f5127cc5822a662136db97", "receipt": { "to": null, "from": "0xb5Ca125166C1987A35EDD550E16846Fa1e1D9bB3", - "contractAddress": "0x00b089E0A6fdE24cf8978994c7BcD24fc1D79825", - "transactionIndex": 86, - "gasUsed": "848547", + "contractAddress": "0x2A8Bf5E47FDcceA8Ab31A995C25198996D5ac514", + "transactionIndex": 145, + "gasUsed": "1184549", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x57030dfb47a4d8849d866b294eb35a5342e7273cf170b443aa3d512f9850c35b", - "transactionHash": "0xfbda17788d3c9cabb36554434e15de11550808248c0ce91e46d99562d54e5fa9", + "blockHash": "0xdc359b7bbbca6bb854b228fef97081b90aaedb60ff522dcae7c148c7dec7d1f4", + "transactionHash": "0xd64b5a21c53cd3281ea5a9384ffd4ecb357e8bb523f5127cc5822a662136db97", "logs": [], - "blockNumber": 20274209, - "cumulativeGasUsed": "9373105", + "blockNumber": 20729758, + "cumulativeGasUsed": "13800573", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "88a7dc38a4aa54f89c0bd740dfe90545", - "metadata": "{\"compiler\":{\"version\":\"0.8.19+commit.7dd6d404\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"NAME\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contract IHats\",\"name\":\"hatsProtocol\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"hatsAccountImplementation\",\"type\":\"address\"},{\"internalType\":\"contract IERC6551Registry\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"keyValuePairs\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"topHatDetails\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"topHatImageURI\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxSupply\",\"type\":\"uint32\"},{\"internalType\":\"string\",\"name\":\"details\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"imageURI\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isMutable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"wearer\",\"type\":\"address\"}],\"internalType\":\"struct DecentHats_0_1_0.Hat\",\"name\":\"adminHat\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxSupply\",\"type\":\"uint32\"},{\"internalType\":\"string\",\"name\":\"details\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"imageURI\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isMutable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"wearer\",\"type\":\"address\"}],\"internalType\":\"struct DecentHats_0_1_0.Hat[]\",\"name\":\"hats\",\"type\":\"tuple[]\"}],\"internalType\":\"struct DecentHats_0_1_0.CreateTreeParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"createAndDeclareTree\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/DecentHats_0_1_0.sol\":\"DecentHats_0_1_0\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.7.0 <0.9.0;\\n\\n/// @title Enum - Collection of enums\\n/// @author Richard Meissner - \\ncontract Enum {\\n enum Operation {Call, DelegateCall}\\n}\\n\",\"keccak256\":\"0x473e45b1a5cc47be494b0e123c9127f0c11c1e0992a321ae5a644c0bfdb2c14f\",\"license\":\"LGPL-3.0-only\"},\"@gnosis.pm/zodiac/contracts/interfaces/IAvatar.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\n\\n/// @title Zodiac Avatar - A contract that manages modules that can execute transactions via this contract.\\npragma solidity >=0.7.0 <0.9.0;\\n\\nimport \\\"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\\\";\\n\\ninterface IAvatar {\\n event EnabledModule(address module);\\n event DisabledModule(address module);\\n event ExecutionFromModuleSuccess(address indexed module);\\n event ExecutionFromModuleFailure(address indexed module);\\n\\n /// @dev Enables a module on the avatar.\\n /// @notice Can only be called by the avatar.\\n /// @notice Modules should be stored as a linked list.\\n /// @notice Must emit EnabledModule(address module) if successful.\\n /// @param module Module to be enabled.\\n function enableModule(address module) external;\\n\\n /// @dev Disables a module on the avatar.\\n /// @notice Can only be called by the avatar.\\n /// @notice Must emit DisabledModule(address module) if successful.\\n /// @param prevModule Address that pointed to the module to be removed in the linked list\\n /// @param module Module to be removed.\\n function disableModule(address prevModule, address module) external;\\n\\n /// @dev Allows a Module to execute a transaction.\\n /// @notice Can only be called by an enabled module.\\n /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.\\n /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.\\n /// @param to Destination address of module transaction.\\n /// @param value Ether value of module transaction.\\n /// @param data Data payload of module transaction.\\n /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.\\n function execTransactionFromModule(\\n address to,\\n uint256 value,\\n bytes memory data,\\n Enum.Operation operation\\n ) external returns (bool success);\\n\\n /// @dev Allows a Module to execute a transaction and return data\\n /// @notice Can only be called by an enabled module.\\n /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.\\n /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.\\n /// @param to Destination address of module transaction.\\n /// @param value Ether value of module transaction.\\n /// @param data Data payload of module transaction.\\n /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.\\n function execTransactionFromModuleReturnData(\\n address to,\\n uint256 value,\\n bytes memory data,\\n Enum.Operation operation\\n ) external returns (bool success, bytes memory returnData);\\n\\n /// @dev Returns if an module is enabled\\n /// @return True if the module is enabled\\n function isModuleEnabled(address module) external view returns (bool);\\n\\n /// @dev Returns array of modules.\\n /// @param start Start of the page.\\n /// @param pageSize Maximum number of modules that should be returned.\\n /// @return array Array of modules.\\n /// @return next Start of the next page.\\n function getModulesPaginated(address start, uint256 pageSize)\\n external\\n view\\n returns (address[] memory array, address next);\\n}\\n\",\"keccak256\":\"0xcd5508ffe596eef8fbccfd5fc4f10a34397773547ce64e212d48b5212865ec1f\",\"license\":\"LGPL-3.0-only\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n}\\n\",\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\"},\"contracts/DecentHats_0_1_0.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity =0.8.19;\\n\\nimport {Enum} from \\\"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\\\";\\nimport {IAvatar} from \\\"@gnosis.pm/zodiac/contracts/interfaces/IAvatar.sol\\\";\\nimport {Strings} from \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\nimport {IERC6551Registry} from \\\"./interfaces/IERC6551Registry.sol\\\";\\nimport {IHats} from \\\"./interfaces/hats/IHats.sol\\\";\\n\\ncontract DecentHats_0_1_0 {\\n string public constant NAME = \\\"DecentHats_0_1_0\\\";\\n\\n struct Hat {\\n uint32 maxSupply;\\n string details;\\n string imageURI;\\n bool isMutable;\\n address wearer;\\n }\\n\\n struct CreateTreeParams {\\n IHats hatsProtocol;\\n address hatsAccountImplementation;\\n IERC6551Registry registry;\\n address keyValuePairs;\\n string topHatDetails;\\n string topHatImageURI;\\n Hat adminHat;\\n Hat[] hats;\\n }\\n\\n function getSalt() internal view returns (bytes32 salt) {\\n uint256 chainId;\\n assembly {\\n chainId := chainid()\\n }\\n\\n bytes memory concatenatedSaltInput = abi.encodePacked(\\n NAME,\\n chainId,\\n address(this)\\n );\\n\\n salt = keccak256(concatenatedSaltInput);\\n }\\n\\n function createTopHat(\\n IHats _hatsProtocol,\\n string memory _topHatDetails,\\n string memory _topHatImageURI\\n ) internal returns (uint256) {\\n return\\n _hatsProtocol.mintTopHat(\\n address(this),\\n _topHatDetails,\\n _topHatImageURI\\n );\\n }\\n\\n function createAccount(\\n IERC6551Registry _registry,\\n address _hatsAccountImplementation,\\n bytes32 salt,\\n address protocolAddress,\\n uint256 hatId\\n ) internal returns (address) {\\n return\\n _registry.createAccount(\\n _hatsAccountImplementation,\\n salt,\\n block.chainid,\\n protocolAddress,\\n hatId\\n );\\n }\\n\\n function updateKeyValuePairs(\\n address _keyValuePairs,\\n uint256 topHatId\\n ) internal {\\n string[] memory keys = new string[](1);\\n string[] memory values = new string[](1);\\n keys[0] = \\\"topHatId\\\";\\n values[0] = Strings.toString(topHatId);\\n\\n IAvatar(msg.sender).execTransactionFromModule(\\n _keyValuePairs,\\n 0,\\n abi.encodeWithSignature(\\n \\\"updateValues(string[],string[])\\\",\\n keys,\\n values\\n ),\\n Enum.Operation.Call\\n );\\n }\\n\\n function createHat(\\n IHats _hatsProtocol,\\n uint256 adminHatId,\\n Hat memory _hat,\\n address topHatAccount\\n ) internal returns (uint256) {\\n return\\n _hatsProtocol.createHat(\\n adminHatId,\\n _hat.details,\\n _hat.maxSupply,\\n topHatAccount,\\n topHatAccount,\\n _hat.isMutable,\\n _hat.imageURI\\n );\\n }\\n\\n function createHatAccountMint(\\n IHats hatsProtocol,\\n uint256 adminHatId,\\n Hat calldata hat,\\n address topHatAccount,\\n IERC6551Registry registry,\\n address hatsAccountImplementation,\\n bytes32 salt\\n ) internal returns (uint256 hatId, address accountAddress) {\\n hatId = createHat(hatsProtocol, adminHatId, hat, topHatAccount);\\n\\n accountAddress = createAccount(\\n registry,\\n hatsAccountImplementation,\\n salt,\\n address(hatsProtocol),\\n hatId\\n );\\n\\n if (hat.wearer != address(0)) {\\n hatsProtocol.mintHat(hatId, hat.wearer);\\n }\\n }\\n\\n function handleHats(\\n IHats _hatsProtocol,\\n IERC6551Registry _registry,\\n address _hatsAccountImplementation,\\n bytes32 salt,\\n address topHatAccount,\\n uint256 adminHatId,\\n Hat[] calldata _hats\\n ) internal {\\n for (uint256 i = 0; i < _hats.length; ) {\\n createHatAccountMint(\\n _hatsProtocol,\\n adminHatId,\\n _hats[i],\\n topHatAccount,\\n _registry,\\n _hatsAccountImplementation,\\n salt\\n );\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n function createAndDeclareTree(CreateTreeParams calldata params) public {\\n bytes32 salt = getSalt();\\n uint256 topHatId = createTopHat(\\n params.hatsProtocol,\\n params.topHatDetails,\\n params.topHatImageURI\\n );\\n address topHatAccount = createAccount(\\n params.registry,\\n params.hatsAccountImplementation,\\n salt,\\n address(params.hatsProtocol),\\n topHatId\\n );\\n\\n updateKeyValuePairs(params.keyValuePairs, topHatId);\\n\\n (uint256 adminHatId, ) = createHatAccountMint(\\n params.hatsProtocol,\\n topHatId,\\n params.adminHat,\\n topHatAccount,\\n params.registry,\\n params.hatsAccountImplementation,\\n salt\\n );\\n\\n handleHats(\\n params.hatsProtocol,\\n params.registry,\\n params.hatsAccountImplementation,\\n salt,\\n topHatAccount,\\n adminHatId,\\n params.hats\\n );\\n\\n params.hatsProtocol.transferHat(topHatId, address(this), msg.sender);\\n }\\n}\\n\",\"keccak256\":\"0xd7dbbda48b0f7eedeef3882aab51e93c4881a47bcb09b2f9a20989d22259f027\",\"license\":\"MIT\"},\"contracts/interfaces/IERC6551Registry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IERC6551Registry {\\n /**\\n * @dev Creates a token bound account for a non-fungible token.\\n *\\n * If account has already been created, returns the account address without calling create2.\\n *\\n * Emits ERC6551AccountCreated event.\\n *\\n * @return account The address of the token bound account\\n */\\n function createAccount(\\n address implementation,\\n bytes32 salt,\\n uint256 chainId,\\n address tokenContract,\\n uint256 tokenId\\n ) external returns (address account);\\n}\\n\",\"keccak256\":\"0x64c52de8a8e68398e61dd8b42dda8e9af8cf6abf93bb85629c322440991ea568\",\"license\":\"MIT\"},\"contracts/interfaces/hats/IHats.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0\\n// Copyright (C) 2023 Haberdasher Labs\\n//\\n// This program is free software: you can redistribute it and/or modify\\n// it under the terms of the GNU Affero General Public License as published by\\n// the Free Software Foundation, either version 3 of the License, or\\n// (at your option) any later version.\\n//\\n// This program is distributed in the hope that it will be useful,\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\\n// GNU Affero General Public License for more details.\\n//\\n// You should have received a copy of the GNU Affero General Public License\\n// along with this program. If not, see .\\n\\npragma solidity >=0.8.13;\\n\\ninterface IHats {\\n function mintTopHat(\\n address _target,\\n string memory _details,\\n string memory _imageURI\\n ) external returns (uint256 topHatId);\\n\\n function createHat(\\n uint256 _admin,\\n string calldata _details,\\n uint32 _maxSupply,\\n address _eligibility,\\n address _toggle,\\n bool _mutable,\\n string calldata _imageURI\\n ) external returns (uint256 newHatId);\\n\\n function mintHat(\\n uint256 _hatId,\\n address _wearer\\n ) external returns (bool success);\\n\\n function transferHat(uint256 _hatId, address _from, address _to) external;\\n}\\n\",\"keccak256\":\"0x8e35022f5c0fcf0059033abec78ec890f0cf3bbac09d6d24051cff9679239511\",\"license\":\"AGPL-3.0\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50610e63806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063a3f4df7e1461003b578063c1bce50714610080575b600080fd5b61006a6040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b81525081565b60405161007791906108a5565b60405180910390f35b61009361008e3660046108bf565b610095565b005b600061009f61029d565b9050600061013c6100b36020850185610913565b6100c06080860186610930565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506101029250505060a0870187610930565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061030192505050565b905060006101776101536060860160408701610913565b6101636040870160208801610913565b856101716020890189610913565b8661037f565b905061019261018c6080860160608701610913565b83610415565b60006101d96101a46020870187610913565b846101b260c089018961098e565b856101c360608b0160408c01610913565b6101d360408c0160208d01610913565b8a610595565b5090506102216101ec6020870187610913565b6101fc6060880160408901610913565b61020c6040890160208a01610913565b87868661021c60e08d018d6109ae565b61067b565b61022e6020860186610913565b6040516329287c1b60e21b8152600481018590523060248201523360448201526001600160a01b03919091169063a4a1f06c90606401600060405180830381600087803b15801561027e57600080fd5b505af1158015610292573d6000803e3d6000fd5b505050505050505050565b60008046905060006040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b81525082306040516020016102e2939291906109f8565b60408051601f1981840301815291905280516020909101209392505050565b604051631a64dfad60e01b81526000906001600160a01b03851690631a64dfad9061033490309087908790600401610a31565b6020604051808303816000875af1158015610353573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103779190610a67565b949350505050565b604051638a54c52f60e01b81526001600160a01b0385811660048301526024820185905246604483015283811660648301526084820183905260009190871690638a54c52f9060a4016020604051808303816000875af11580156103e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061040b9190610a80565b9695505050505050565b604080516001808252818301909252600091816020015b606081526020019060019003908161042c57505060408051600180825281830190925291925060009190602082015b606081526020019060019003908161045b579050509050604051806040016040528060088152602001671d1bdc12185d125960c21b815250826000815181106104a6576104a6610ab3565b60200260200101819052506104ba836106c2565b816000815181106104cd576104cd610ab3565b6020026020010181905250336001600160a01b031663468721a785600085856040516024016104fd929190610b1e565b60408051601f198184030181529181526020820180516001600160e01b031663579374b960e11b1790525160e085901b6001600160e01b031916815261054b93929190600090600401610b43565b6020604051808303816000875af115801561056a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058e9190610ba7565b5050505050565b6000806105ac89896105a68a610c85565b896107c3565b91506105bb8585858c8661037f565b905060006105cf60a0890160808a01610913565b6001600160a01b03161461066f576001600160a01b03891663641f776e836105fd60a08b0160808c01610913565b6040516001600160e01b031960e085901b16815260048101929092526001600160a01b031660248201526044016020604051808303816000875af1158015610649573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066d9190610ba7565b505b97509795505050505050565b60005b81811015610292576106b8898585858581811061069d5761069d610ab3565b90506020028101906106af919061098e565b888c8c8c610595565b505060010161067e565b6060816000036106e95750506040805180820190915260018152600360fc1b602082015290565b8160005b811561071357806106fd81610d46565b915061070c9050600a83610d75565b91506106ed565b60008167ffffffffffffffff81111561072e5761072e610a9d565b6040519080825280601f01601f191660200182016040528015610758576020820181803683370190505b5090505b84156103775761076d600183610d89565b915061077a600a86610da2565b610785906030610db6565b60f81b81838151811061079a5761079a610ab3565b60200101906001600160f81b031916908160001a9053506107bc600a86610d75565b945061075c565b6020820151825160608401516040808601519051635829492f60e11b81526000946001600160a01b038a169463b052925e94610809948b948a9283929091600401610dc9565b6020604051808303816000875af1158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c9190610a67565b95945050505050565b60005b83811015610870578181015183820152602001610858565b50506000910152565b60008151808452610891816020860160208601610855565b601f01601f19169290920160200192915050565b6020815260006108b86020830184610879565b9392505050565b6000602082840312156108d157600080fd5b813567ffffffffffffffff8111156108e857600080fd5b820161010081850312156108b857600080fd5b6001600160a01b038116811461091057600080fd5b50565b60006020828403121561092557600080fd5b81356108b8816108fb565b6000808335601e1984360301811261094757600080fd5b83018035915067ffffffffffffffff82111561096257600080fd5b60200191503681900382131561097757600080fd5b9250929050565b8035610989816108fb565b919050565b60008235609e198336030181126109a457600080fd5b9190910192915050565b6000808335601e198436030181126109c557600080fd5b83018035915067ffffffffffffffff8211156109e057600080fd5b6020019150600581901b360382131561097757600080fd5b60008451610a0a818460208901610855565b919091019283525060601b6bffffffffffffffffffffffff19166020820152603401919050565b6001600160a01b0384168152606060208201819052600090610a5590830185610879565b828103604084015261040b8185610879565b600060208284031215610a7957600080fd5b5051919050565b600060208284031215610a9257600080fd5b81516108b8816108fb565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501808196508360051b8101915082860160005b85811015610b11578284038952610aff848351610879565b98850198935090840190600101610ae7565b5091979650505050505050565b604081526000610b316040830185610ac9565b828103602084015261084c8185610ac9565b60018060a01b0385168152836020820152608060408201526000610b6a6080830185610879565b905060028310610b8a57634e487b7160e01b600052602160045260246000fd5b82606083015295945050505050565b801515811461091057600080fd5b600060208284031215610bb957600080fd5b81516108b881610b99565b60405160a0810167ffffffffffffffff81118282101715610be757610be7610a9d565b60405290565b600082601f830112610bfe57600080fd5b813567ffffffffffffffff80821115610c1957610c19610a9d565b604051601f8301601f19908116603f01168101908282118183101715610c4157610c41610a9d565b81604052838152866020858801011115610c5a57600080fd5b836020870160208301376000602085830101528094505050505092915050565b803561098981610b99565b600060a08236031215610c9757600080fd5b610c9f610bc4565b823563ffffffff81168114610cb357600080fd5b8152602083013567ffffffffffffffff80821115610cd057600080fd5b610cdc36838701610bed565b60208401526040850135915080821115610cf557600080fd5b50610d0236828601610bed565b604083015250610d1460608401610c7a565b6060820152610d256080840161097e565b608082015292915050565b634e487b7160e01b600052601160045260246000fd5b600060018201610d5857610d58610d30565b5060010190565b634e487b7160e01b600052601260045260246000fd5b600082610d8457610d84610d5f565b500490565b81810381811115610d9c57610d9c610d30565b92915050565b600082610db157610db1610d5f565b500690565b80820180821115610d9c57610d9c610d30565b87815260e060208201526000610de260e0830189610879565b63ffffffff881660408401526001600160a01b0387811660608501528616608084015284151560a084015282810360c0840152610e1f8185610879565b9a995050505050505050505056fea264697066735822122040470770e7f603d20cdea8118401756a0349e1cdc776519095ccf844ef03c2cd64736f6c63430008130033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c8063a3f4df7e1461003b578063c1bce50714610080575b600080fd5b61006a6040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b81525081565b60405161007791906108a5565b60405180910390f35b61009361008e3660046108bf565b610095565b005b600061009f61029d565b9050600061013c6100b36020850185610913565b6100c06080860186610930565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506101029250505060a0870187610930565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061030192505050565b905060006101776101536060860160408701610913565b6101636040870160208801610913565b856101716020890189610913565b8661037f565b905061019261018c6080860160608701610913565b83610415565b60006101d96101a46020870187610913565b846101b260c089018961098e565b856101c360608b0160408c01610913565b6101d360408c0160208d01610913565b8a610595565b5090506102216101ec6020870187610913565b6101fc6060880160408901610913565b61020c6040890160208a01610913565b87868661021c60e08d018d6109ae565b61067b565b61022e6020860186610913565b6040516329287c1b60e21b8152600481018590523060248201523360448201526001600160a01b03919091169063a4a1f06c90606401600060405180830381600087803b15801561027e57600080fd5b505af1158015610292573d6000803e3d6000fd5b505050505050505050565b60008046905060006040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b81525082306040516020016102e2939291906109f8565b60408051601f1981840301815291905280516020909101209392505050565b604051631a64dfad60e01b81526000906001600160a01b03851690631a64dfad9061033490309087908790600401610a31565b6020604051808303816000875af1158015610353573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103779190610a67565b949350505050565b604051638a54c52f60e01b81526001600160a01b0385811660048301526024820185905246604483015283811660648301526084820183905260009190871690638a54c52f9060a4016020604051808303816000875af11580156103e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061040b9190610a80565b9695505050505050565b604080516001808252818301909252600091816020015b606081526020019060019003908161042c57505060408051600180825281830190925291925060009190602082015b606081526020019060019003908161045b579050509050604051806040016040528060088152602001671d1bdc12185d125960c21b815250826000815181106104a6576104a6610ab3565b60200260200101819052506104ba836106c2565b816000815181106104cd576104cd610ab3565b6020026020010181905250336001600160a01b031663468721a785600085856040516024016104fd929190610b1e565b60408051601f198184030181529181526020820180516001600160e01b031663579374b960e11b1790525160e085901b6001600160e01b031916815261054b93929190600090600401610b43565b6020604051808303816000875af115801561056a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058e9190610ba7565b5050505050565b6000806105ac89896105a68a610c85565b896107c3565b91506105bb8585858c8661037f565b905060006105cf60a0890160808a01610913565b6001600160a01b03161461066f576001600160a01b03891663641f776e836105fd60a08b0160808c01610913565b6040516001600160e01b031960e085901b16815260048101929092526001600160a01b031660248201526044016020604051808303816000875af1158015610649573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066d9190610ba7565b505b97509795505050505050565b60005b81811015610292576106b8898585858581811061069d5761069d610ab3565b90506020028101906106af919061098e565b888c8c8c610595565b505060010161067e565b6060816000036106e95750506040805180820190915260018152600360fc1b602082015290565b8160005b811561071357806106fd81610d46565b915061070c9050600a83610d75565b91506106ed565b60008167ffffffffffffffff81111561072e5761072e610a9d565b6040519080825280601f01601f191660200182016040528015610758576020820181803683370190505b5090505b84156103775761076d600183610d89565b915061077a600a86610da2565b610785906030610db6565b60f81b81838151811061079a5761079a610ab3565b60200101906001600160f81b031916908160001a9053506107bc600a86610d75565b945061075c565b6020820151825160608401516040808601519051635829492f60e11b81526000946001600160a01b038a169463b052925e94610809948b948a9283929091600401610dc9565b6020604051808303816000875af1158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c9190610a67565b95945050505050565b60005b83811015610870578181015183820152602001610858565b50506000910152565b60008151808452610891816020860160208601610855565b601f01601f19169290920160200192915050565b6020815260006108b86020830184610879565b9392505050565b6000602082840312156108d157600080fd5b813567ffffffffffffffff8111156108e857600080fd5b820161010081850312156108b857600080fd5b6001600160a01b038116811461091057600080fd5b50565b60006020828403121561092557600080fd5b81356108b8816108fb565b6000808335601e1984360301811261094757600080fd5b83018035915067ffffffffffffffff82111561096257600080fd5b60200191503681900382131561097757600080fd5b9250929050565b8035610989816108fb565b919050565b60008235609e198336030181126109a457600080fd5b9190910192915050565b6000808335601e198436030181126109c557600080fd5b83018035915067ffffffffffffffff8211156109e057600080fd5b6020019150600581901b360382131561097757600080fd5b60008451610a0a818460208901610855565b919091019283525060601b6bffffffffffffffffffffffff19166020820152603401919050565b6001600160a01b0384168152606060208201819052600090610a5590830185610879565b828103604084015261040b8185610879565b600060208284031215610a7957600080fd5b5051919050565b600060208284031215610a9257600080fd5b81516108b8816108fb565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501808196508360051b8101915082860160005b85811015610b11578284038952610aff848351610879565b98850198935090840190600101610ae7565b5091979650505050505050565b604081526000610b316040830185610ac9565b828103602084015261084c8185610ac9565b60018060a01b0385168152836020820152608060408201526000610b6a6080830185610879565b905060028310610b8a57634e487b7160e01b600052602160045260246000fd5b82606083015295945050505050565b801515811461091057600080fd5b600060208284031215610bb957600080fd5b81516108b881610b99565b60405160a0810167ffffffffffffffff81118282101715610be757610be7610a9d565b60405290565b600082601f830112610bfe57600080fd5b813567ffffffffffffffff80821115610c1957610c19610a9d565b604051601f8301601f19908116603f01168101908282118183101715610c4157610c41610a9d565b81604052838152866020858801011115610c5a57600080fd5b836020870160208301376000602085830101528094505050505092915050565b803561098981610b99565b600060a08236031215610c9757600080fd5b610c9f610bc4565b823563ffffffff81168114610cb357600080fd5b8152602083013567ffffffffffffffff80821115610cd057600080fd5b610cdc36838701610bed565b60208401526040850135915080821115610cf557600080fd5b50610d0236828601610bed565b604083015250610d1460608401610c7a565b6060820152610d256080840161097e565b608082015292915050565b634e487b7160e01b600052601160045260246000fd5b600060018201610d5857610d58610d30565b5060010190565b634e487b7160e01b600052601260045260246000fd5b600082610d8457610d84610d5f565b500490565b81810381811115610d9c57610d9c610d30565b92915050565b600082610db157610db1610d5f565b500690565b80820180821115610d9c57610d9c610d30565b87815260e060208201526000610de260e0830189610879565b63ffffffff881660408401526001600160a01b0387811660608501528616608084015284151560a084015282810360c0840152610e1f8185610879565b9a995050505050505050505056fea264697066735822122040470770e7f603d20cdea8118401756a0349e1cdc776519095ccf844ef03c2cd64736f6c63430008130033", + "numDeployments": 2, + "solcInputHash": "512807b5d71481c693c202ae23158904", + "metadata": "{\"compiler\":{\"version\":\"0.8.19+commit.7dd6d404\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"NAME\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contract IHats\",\"name\":\"hatsProtocol\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"hatsAccountImplementation\",\"type\":\"address\"},{\"internalType\":\"contract IERC6551Registry\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"keyValuePairs\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"topHatDetails\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"topHatImageURI\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxSupply\",\"type\":\"uint32\"},{\"internalType\":\"string\",\"name\":\"details\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"imageURI\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isMutable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"wearer\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"contract ISablierV2LockupLinear\",\"name\":\"sablier\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint128\",\"name\":\"totalAmount\",\"type\":\"uint128\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"cancelable\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"transferable\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"uint40\",\"name\":\"start\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"cliff\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"end\",\"type\":\"uint40\"}],\"internalType\":\"struct LockupLinear.Timestamps\",\"name\":\"timestamps\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"}],\"internalType\":\"struct LockupLinear.Broker\",\"name\":\"broker\",\"type\":\"tuple\"}],\"internalType\":\"struct DecentHats_0_1_0.SablierStreamParams[]\",\"name\":\"sablierParams\",\"type\":\"tuple[]\"}],\"internalType\":\"struct DecentHats_0_1_0.Hat\",\"name\":\"adminHat\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxSupply\",\"type\":\"uint32\"},{\"internalType\":\"string\",\"name\":\"details\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"imageURI\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isMutable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"wearer\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"contract ISablierV2LockupLinear\",\"name\":\"sablier\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint128\",\"name\":\"totalAmount\",\"type\":\"uint128\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"cancelable\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"transferable\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"uint40\",\"name\":\"start\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"cliff\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"end\",\"type\":\"uint40\"}],\"internalType\":\"struct LockupLinear.Timestamps\",\"name\":\"timestamps\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"}],\"internalType\":\"struct LockupLinear.Broker\",\"name\":\"broker\",\"type\":\"tuple\"}],\"internalType\":\"struct DecentHats_0_1_0.SablierStreamParams[]\",\"name\":\"sablierParams\",\"type\":\"tuple[]\"}],\"internalType\":\"struct DecentHats_0_1_0.Hat[]\",\"name\":\"hats\",\"type\":\"tuple[]\"}],\"internalType\":\"struct DecentHats_0_1_0.CreateTreeParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"createAndDeclareTree\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/DecentHats_0_1_0.sol\":\"DecentHats_0_1_0\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.7.0 <0.9.0;\\n\\n/// @title Enum - Collection of enums\\n/// @author Richard Meissner - \\ncontract Enum {\\n enum Operation {Call, DelegateCall}\\n}\\n\",\"keccak256\":\"0x473e45b1a5cc47be494b0e123c9127f0c11c1e0992a321ae5a644c0bfdb2c14f\",\"license\":\"LGPL-3.0-only\"},\"@gnosis.pm/zodiac/contracts/interfaces/IAvatar.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\n\\n/// @title Zodiac Avatar - A contract that manages modules that can execute transactions via this contract.\\npragma solidity >=0.7.0 <0.9.0;\\n\\nimport \\\"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\\\";\\n\\ninterface IAvatar {\\n event EnabledModule(address module);\\n event DisabledModule(address module);\\n event ExecutionFromModuleSuccess(address indexed module);\\n event ExecutionFromModuleFailure(address indexed module);\\n\\n /// @dev Enables a module on the avatar.\\n /// @notice Can only be called by the avatar.\\n /// @notice Modules should be stored as a linked list.\\n /// @notice Must emit EnabledModule(address module) if successful.\\n /// @param module Module to be enabled.\\n function enableModule(address module) external;\\n\\n /// @dev Disables a module on the avatar.\\n /// @notice Can only be called by the avatar.\\n /// @notice Must emit DisabledModule(address module) if successful.\\n /// @param prevModule Address that pointed to the module to be removed in the linked list\\n /// @param module Module to be removed.\\n function disableModule(address prevModule, address module) external;\\n\\n /// @dev Allows a Module to execute a transaction.\\n /// @notice Can only be called by an enabled module.\\n /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.\\n /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.\\n /// @param to Destination address of module transaction.\\n /// @param value Ether value of module transaction.\\n /// @param data Data payload of module transaction.\\n /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.\\n function execTransactionFromModule(\\n address to,\\n uint256 value,\\n bytes memory data,\\n Enum.Operation operation\\n ) external returns (bool success);\\n\\n /// @dev Allows a Module to execute a transaction and return data\\n /// @notice Can only be called by an enabled module.\\n /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.\\n /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.\\n /// @param to Destination address of module transaction.\\n /// @param value Ether value of module transaction.\\n /// @param data Data payload of module transaction.\\n /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.\\n function execTransactionFromModuleReturnData(\\n address to,\\n uint256 value,\\n bytes memory data,\\n Enum.Operation operation\\n ) external returns (bool success, bytes memory returnData);\\n\\n /// @dev Returns if an module is enabled\\n /// @return True if the module is enabled\\n function isModuleEnabled(address module) external view returns (bool);\\n\\n /// @dev Returns array of modules.\\n /// @param start Start of the page.\\n /// @param pageSize Maximum number of modules that should be returned.\\n /// @return array Array of modules.\\n /// @return next Start of the next page.\\n function getModulesPaginated(address start, uint256 pageSize)\\n external\\n view\\n returns (address[] memory array, address next);\\n}\\n\",\"keccak256\":\"0xcd5508ffe596eef8fbccfd5fc4f10a34397773547ce64e212d48b5212865ec1f\",\"license\":\"LGPL-3.0-only\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n}\\n\",\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\"},\"contracts/DecentHats_0_1_0.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity =0.8.19;\\n\\nimport {Enum} from \\\"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\\\";\\nimport {IAvatar} from \\\"@gnosis.pm/zodiac/contracts/interfaces/IAvatar.sol\\\";\\nimport {Strings} from \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {IERC6551Registry} from \\\"./interfaces/IERC6551Registry.sol\\\";\\nimport {IHats} from \\\"./interfaces/hats/IHats.sol\\\";\\nimport {ISablierV2LockupLinear} from \\\"./interfaces/sablier/ISablierV2LockupLinear.sol\\\";\\nimport {LockupLinear} from \\\"./interfaces/sablier/LockupLinear.sol\\\";\\n\\ncontract DecentHats_0_1_0 {\\n string public constant NAME = \\\"DecentHats_0_1_0\\\";\\n\\n struct SablierStreamParams {\\n ISablierV2LockupLinear sablier;\\n address sender;\\n uint128 totalAmount;\\n address asset;\\n bool cancelable;\\n bool transferable;\\n LockupLinear.Timestamps timestamps;\\n LockupLinear.Broker broker;\\n }\\n\\n struct Hat {\\n uint32 maxSupply;\\n string details;\\n string imageURI;\\n bool isMutable;\\n address wearer;\\n SablierStreamParams[] sablierParams; // Optional Sablier stream parameters\\n }\\n\\n struct CreateTreeParams {\\n IHats hatsProtocol;\\n address hatsAccountImplementation;\\n IERC6551Registry registry;\\n address keyValuePairs;\\n string topHatDetails;\\n string topHatImageURI;\\n Hat adminHat;\\n Hat[] hats;\\n }\\n\\n function getSalt() internal view returns (bytes32 salt) {\\n uint256 chainId;\\n assembly {\\n chainId := chainid()\\n }\\n\\n bytes memory concatenatedSaltInput = abi.encodePacked(\\n NAME,\\n chainId,\\n address(this)\\n );\\n\\n salt = keccak256(concatenatedSaltInput);\\n }\\n\\n function updateKeyValuePairs(\\n address _keyValuePairs,\\n uint256 topHatId\\n ) internal {\\n string[] memory keys = new string[](1);\\n string[] memory values = new string[](1);\\n keys[0] = \\\"topHatId\\\";\\n values[0] = Strings.toString(topHatId);\\n\\n IAvatar(msg.sender).execTransactionFromModule(\\n _keyValuePairs,\\n 0,\\n abi.encodeWithSignature(\\n \\\"updateValues(string[],string[])\\\",\\n keys,\\n values\\n ),\\n Enum.Operation.Call\\n );\\n }\\n\\n function createHat(\\n IHats _hatsProtocol,\\n uint256 adminHatId,\\n Hat memory _hat,\\n address topHatAccount\\n ) internal returns (uint256) {\\n return\\n _hatsProtocol.createHat(\\n adminHatId,\\n _hat.details,\\n _hat.maxSupply,\\n topHatAccount,\\n topHatAccount,\\n _hat.isMutable,\\n _hat.imageURI\\n );\\n }\\n\\n function createAccount(\\n IERC6551Registry _registry,\\n address _hatsAccountImplementation,\\n bytes32 salt,\\n address protocolAddress,\\n uint256 hatId\\n ) internal returns (address) {\\n return\\n _registry.createAccount(\\n _hatsAccountImplementation,\\n salt,\\n block.chainid,\\n protocolAddress,\\n hatId\\n );\\n }\\n\\n function createTopHatAndAccount(\\n IHats _hatsProtocol,\\n string memory _topHatDetails,\\n string memory _topHatImageURI,\\n IERC6551Registry _registry,\\n address _hatsAccountImplementation,\\n bytes32 salt\\n ) internal returns (uint256 topHatId, address topHatAccount) {\\n topHatId = _hatsProtocol.mintTopHat(\\n address(this),\\n _topHatDetails,\\n _topHatImageURI\\n );\\n\\n topHatAccount = createAccount(\\n _registry,\\n _hatsAccountImplementation,\\n salt,\\n address(_hatsProtocol),\\n topHatId\\n );\\n }\\n\\n function createHatAndAccountAndMintAndStreams(\\n IHats hatsProtocol,\\n uint256 adminHatId,\\n Hat calldata hat,\\n address topHatAccount,\\n IERC6551Registry registry,\\n address hatsAccountImplementation,\\n bytes32 salt\\n ) internal returns (uint256 hatId, address accountAddress) {\\n hatId = createHat(hatsProtocol, adminHatId, hat, topHatAccount);\\n\\n accountAddress = createAccount(\\n registry,\\n hatsAccountImplementation,\\n salt,\\n address(hatsProtocol),\\n hatId\\n );\\n\\n if (hat.wearer != address(0)) {\\n hatsProtocol.mintHat(hatId, hat.wearer);\\n }\\n\\n for (uint256 i = 0; i < hat.sablierParams.length; ) {\\n SablierStreamParams memory sablierParams = hat.sablierParams[i];\\n\\n // Approve tokens for Sablier\\n IAvatar(msg.sender).execTransactionFromModule(\\n sablierParams.asset,\\n 0,\\n abi.encodeWithSignature(\\n \\\"approve(address,uint256)\\\",\\n address(sablierParams.sablier),\\n sablierParams.totalAmount\\n ),\\n Enum.Operation.Call\\n );\\n\\n LockupLinear.CreateWithTimestamps memory params = LockupLinear\\n .CreateWithTimestamps({\\n sender: sablierParams.sender,\\n recipient: accountAddress,\\n totalAmount: sablierParams.totalAmount,\\n asset: IERC20(sablierParams.asset),\\n cancelable: sablierParams.cancelable,\\n transferable: sablierParams.transferable,\\n timestamps: sablierParams.timestamps,\\n broker: sablierParams.broker\\n });\\n\\n // Proxy the Sablier call through IAvatar\\n IAvatar(msg.sender).execTransactionFromModule(\\n address(sablierParams.sablier),\\n 0,\\n abi.encodeWithSignature(\\n \\\"createWithTimestamps((address,address,uint128,address,bool,bool,(uint40,uint40,uint40),(address,uint256)))\\\",\\n params\\n ),\\n Enum.Operation.Call\\n );\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n function createAndDeclareTree(CreateTreeParams calldata params) public {\\n bytes32 salt = getSalt();\\n\\n (uint256 topHatId, address topHatAccount) = createTopHatAndAccount(\\n params.hatsProtocol,\\n params.topHatDetails,\\n params.topHatImageURI,\\n params.registry,\\n params.hatsAccountImplementation,\\n salt\\n );\\n\\n updateKeyValuePairs(params.keyValuePairs, topHatId);\\n\\n (uint256 adminHatId, ) = createHatAndAccountAndMintAndStreams(\\n params.hatsProtocol,\\n topHatId,\\n params.adminHat,\\n topHatAccount,\\n params.registry,\\n params.hatsAccountImplementation,\\n salt\\n );\\n\\n for (uint256 i = 0; i < params.hats.length; ) {\\n createHatAndAccountAndMintAndStreams(\\n params.hatsProtocol,\\n adminHatId,\\n params.hats[i],\\n topHatAccount,\\n params.registry,\\n params.hatsAccountImplementation,\\n salt\\n );\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n params.hatsProtocol.transferHat(topHatId, address(this), msg.sender);\\n }\\n}\\n\",\"keccak256\":\"0xdc0d2b3c556d675f26152895a17e1fb76c91d1a85b2689cf435fb3666381ac41\",\"license\":\"MIT\"},\"contracts/interfaces/IERC6551Registry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IERC6551Registry {\\n /**\\n * @dev Creates a token bound account for a non-fungible token.\\n *\\n * If account has already been created, returns the account address without calling create2.\\n *\\n * Emits ERC6551AccountCreated event.\\n *\\n * @return account The address of the token bound account\\n */\\n function createAccount(\\n address implementation,\\n bytes32 salt,\\n uint256 chainId,\\n address tokenContract,\\n uint256 tokenId\\n ) external returns (address account);\\n}\\n\",\"keccak256\":\"0x64c52de8a8e68398e61dd8b42dda8e9af8cf6abf93bb85629c322440991ea568\",\"license\":\"MIT\"},\"contracts/interfaces/hats/IHats.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0\\n// Copyright (C) 2023 Haberdasher Labs\\n//\\n// This program is free software: you can redistribute it and/or modify\\n// it under the terms of the GNU Affero General Public License as published by\\n// the Free Software Foundation, either version 3 of the License, or\\n// (at your option) any later version.\\n//\\n// This program is distributed in the hope that it will be useful,\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\\n// GNU Affero General Public License for more details.\\n//\\n// You should have received a copy of the GNU Affero General Public License\\n// along with this program. If not, see .\\n\\npragma solidity >=0.8.13;\\n\\ninterface IHats {\\n function mintTopHat(\\n address _target,\\n string memory _details,\\n string memory _imageURI\\n ) external returns (uint256 topHatId);\\n\\n function createHat(\\n uint256 _admin,\\n string calldata _details,\\n uint32 _maxSupply,\\n address _eligibility,\\n address _toggle,\\n bool _mutable,\\n string calldata _imageURI\\n ) external returns (uint256 newHatId);\\n\\n function mintHat(\\n uint256 _hatId,\\n address _wearer\\n ) external returns (bool success);\\n\\n function transferHat(uint256 _hatId, address _from, address _to) external;\\n}\\n\",\"keccak256\":\"0x8e35022f5c0fcf0059033abec78ec890f0cf3bbac09d6d24051cff9679239511\",\"license\":\"AGPL-3.0\"},\"contracts/interfaces/sablier/ISablierV2LockupLinear.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {LockupLinear} from \\\"./LockupLinear.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface ISablierV2LockupLinear {\\n function createWithTimestamps(\\n LockupLinear.CreateWithTimestamps calldata params\\n ) external returns (uint256 streamId);\\n}\\n\",\"keccak256\":\"0xf4899637eb2e6c76c35e2d201e56e162a50e6bc7b5b9156e00866f0703ad07ca\",\"license\":\"MIT\"},\"contracts/interfaces/sablier/LockupLinear.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LockupLinear {\\n struct CreateWithTimestamps {\\n address sender;\\n address recipient;\\n uint128 totalAmount;\\n IERC20 asset;\\n bool cancelable;\\n bool transferable;\\n Timestamps timestamps;\\n Broker broker;\\n }\\n\\n struct Timestamps {\\n uint40 start;\\n uint40 cliff;\\n uint40 end;\\n }\\n\\n struct Broker {\\n address account;\\n uint256 fee;\\n }\\n}\\n\",\"keccak256\":\"0x497fdb52b5e1a5a7e0711a9f7d5fb036eb668ccb92ea908ee088f56ee08a4ce8\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50611477806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80638c5f591a1461003b578063a3f4df7e14610050575b600080fd5b61004e610049366004610ac2565b610095565b005b61007f6040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b81525081565b60405161008c9190610b54565b60405180910390f35b600061009f6102cd565b905060008061015e6100b46020860186610b7f565b6100c16080870187610b9c565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506101039250505060a0880188610b9c565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610148925050506060890160408a01610b7f565b61015860408a0160208b01610b7f565b88610331565b909250905061017c6101766080860160608701610b7f565b836103c3565b60006101c361018e6020870187610b7f565b8461019c60c0890189610bf9565b856101ad60608b0160408c01610b7f565b6101bd60408c0160208d01610b7f565b8a610543565b50905060005b6101d660e0870187610c19565b9050811015610250576102466101ef6020880188610b7f565b836101fd60e08a018a610c19565b8581811061020d5761020d610c62565b905060200281019061021f9190610bf9565b8661023060608c0160408d01610b7f565b61024060408d0160208e01610b7f565b8b610543565b50506001016101c9565b5061025e6020860186610b7f565b6040516329287c1b60e21b8152600481018590523060248201523360448201526001600160a01b03919091169063a4a1f06c90606401600060405180830381600087803b1580156102ae57600080fd5b505af11580156102c2573d6000803e3d6000fd5b505050505050505050565b60008046905060006040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b815250823060405160200161031293929190610c78565b60408051601f1981840301815291905280516020909101209392505050565b600080876001600160a01b0316631a64dfad3089896040518463ffffffff1660e01b815260040161036493929190610cb1565b6020604051808303816000875af1158015610383573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a79190610ce7565b91506103b68585858b86610892565b9050965096945050505050565b604080516001808252818301909252600091816020015b60608152602001906001900390816103da57505060408051600180825281830190925291925060009190602082015b6060815260200190600190039081610409579050509050604051806040016040528060088152602001671d1bdc12185d125960c21b8152508260008151811061045457610454610c62565b602002602001018190525061046883610928565b8160008151811061047b5761047b610c62565b6020026020010181905250336001600160a01b031663468721a785600085856040516024016104ab929190610d6b565b60408051601f198184030181529181526020820180516001600160e01b031663579374b960e11b1790525160e085901b6001600160e01b03191681526104f993929190600090600401610d90565b6020604051808303816000875af1158015610518573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053c9190610df4565b5050505050565b60008061055a89896105548a61113b565b89610a30565b91506105698585858c86610892565b9050600061057d60a0890160808a01610b7f565b6001600160a01b03161461061d576001600160a01b03891663641f776e836105ab60a08b0160808c01610b7f565b6040516001600160e01b031960e085901b16815260048101929092526001600160a01b031660248201526044016020604051808303816000875af11580156105f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061b9190610df4565b505b60005b61062d60a08901896111ff565b905081101561088557600061064560a08a018a6111ff565b8381811061065557610655610c62565b9050610160020180360381019061066c9190611248565b6060810151815160408084015190516001600160a01b0390921660248301526001600160801b03166044820152919250339163468721a7919060009060640160408051601f198184030181529181526020820180516001600160e01b031663095ea7b360e01b1790525160e085901b6001600160e01b03191681526106f993929190600090600401610d90565b6020604051808303816000875af1158015610718573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073c9190610df4565b50600060405180610100016040528083602001516001600160a01b03168152602001856001600160a01b0316815260200183604001516001600160801b0316815260200183606001516001600160a01b031681526020018360800151151581526020018360a00151151581526020018360c0015181526020018360e001518152509050336001600160a01b031663468721a783600001516000846040516024016107e69190611265565b60408051601f198184030181529181526020820180516001600160e01b03166353b1572760e01b1790525160e085901b6001600160e01b031916815261083493929190600090600401610d90565b6020604051808303816000875af1158015610853573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108779190610df4565b508260010192505050610620565b5097509795505050505050565b604051638a54c52f60e01b81526001600160a01b0385811660048301526024820185905246604483015283811660648301526084820183905260009190871690638a54c52f9060a4016020604051808303816000875af11580156108fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091e9190611327565b9695505050505050565b60608160000361094f5750506040805180820190915260018152600360fc1b602082015290565b8160005b811561097957806109638161135a565b91506109729050600a83611389565b9150610953565b6000816001600160401b0381111561099357610993610d00565b6040519080825280601f01601f1916602001820160405280156109bd576020820181803683370190505b5090505b8415610a28576109d260018361139d565b91506109df600a866113b6565b6109ea9060306113ca565b60f81b8183815181106109ff576109ff610c62565b60200101906001600160f81b031916908160001a905350610a21600a86611389565b94506109c1565b949350505050565b6020820151825160608401516040808601519051635829492f60e11b81526000946001600160a01b038a169463b052925e94610a76948b948a92839290916004016113dd565b6020604051808303816000875af1158015610a95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab99190610ce7565b95945050505050565b600060208284031215610ad457600080fd5b81356001600160401b03811115610aea57600080fd5b82016101008185031215610afd57600080fd5b9392505050565b60005b83811015610b1f578181015183820152602001610b07565b50506000910152565b60008151808452610b40816020860160208601610b04565b601f01601f19169290920160200192915050565b602081526000610afd6020830184610b28565b6001600160a01b0381168114610b7c57600080fd5b50565b600060208284031215610b9157600080fd5b8135610afd81610b67565b6000808335601e19843603018112610bb357600080fd5b8301803591506001600160401b03821115610bcd57600080fd5b602001915036819003821315610be257600080fd5b9250929050565b8035610bf481610b67565b919050565b6000823560be19833603018112610c0f57600080fd5b9190910192915050565b6000808335601e19843603018112610c3057600080fd5b8301803591506001600160401b03821115610c4a57600080fd5b6020019150600581901b3603821315610be257600080fd5b634e487b7160e01b600052603260045260246000fd5b60008451610c8a818460208901610b04565b919091019283525060601b6bffffffffffffffffffffffff19166020820152603401919050565b6001600160a01b0384168152606060208201819052600090610cd590830185610b28565b828103604084015261091e8185610b28565b600060208284031215610cf957600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b600081518084526020808501808196508360051b8101915082860160005b85811015610d5e578284038952610d4c848351610b28565b98850198935090840190600101610d34565b5091979650505050505050565b604081526000610d7e6040830185610d16565b8281036020840152610ab98185610d16565b60018060a01b0385168152836020820152608060408201526000610db76080830185610b28565b905060028310610dd757634e487b7160e01b600052602160045260246000fd5b82606083015295945050505050565b8015158114610b7c57600080fd5b600060208284031215610e0657600080fd5b8151610afd81610de6565b60405160c081016001600160401b0381118282101715610e3357610e33610d00565b60405290565b604051601f8201601f191681016001600160401b0381118282101715610e6157610e61610d00565b604052919050565b803563ffffffff81168114610bf457600080fd5b600082601f830112610e8e57600080fd5b81356001600160401b03811115610ea757610ea7610d00565b610eba601f8201601f1916602001610e39565b818152846020838601011115610ecf57600080fd5b816020850160208301376000918101602001919091529392505050565b8035610bf481610de6565b80356001600160801b0381168114610bf457600080fd5b803564ffffffffff81168114610bf457600080fd5b600060608284031215610f3557600080fd5b604051606081018181106001600160401b0382111715610f5757610f57610d00565b604052905080610f6683610f0e565b8152610f7460208401610f0e565b6020820152610f8560408401610f0e565b60408201525092915050565b600060408284031215610fa357600080fd5b604051604081018181106001600160401b0382111715610fc557610fc5610d00565b6040529050808235610fd681610b67565b8152602092830135920191909152919050565b60006101608284031215610ffc57600080fd5b60405161010081018181106001600160401b038211171561101f5761101f610d00565b60405290508061102e83610be9565b815261103c60208401610be9565b602082015261104d60408401610ef7565b604082015261105e60608401610be9565b606082015261106f60808401610eec565b608082015261108060a08401610eec565b60a08201526110928460c08501610f23565b60c08201526110a5846101208501610f91565b60e08201525092915050565b600082601f8301126110c257600080fd5b813560206001600160401b038211156110dd576110dd610d00565b6110eb818360051b01610e39565b828152610160928302850182019282820191908785111561110b57600080fd5b8387015b8581101561112e576111218982610fe9565b845292840192810161110f565b5090979650505050505050565b600060c0823603121561114d57600080fd5b611155610e11565b61115e83610e69565b815260208301356001600160401b038082111561117a57600080fd5b61118636838701610e7d565b6020840152604085013591508082111561119f57600080fd5b6111ab36838701610e7d565b60408401526111bc60608601610eec565b60608401526111cd60808601610be9565b608084015260a08501359150808211156111e657600080fd5b506111f3368286016110b1565b60a08301525092915050565b6000808335601e1984360301811261121657600080fd5b8301803591506001600160401b0382111561123057600080fd5b602001915061016081023603821315610be257600080fd5b6000610160828403121561125b57600080fd5b610afd8383610fe9565b81516001600160a01b0390811682526020808401518216908301526040808401516001600160801b031690830152606080840151909116908201526080808301516101608301916112b99084018215159052565b5060a08301516112cd60a084018215159052565b5060c083015161130060c0840182805164ffffffffff908116835260208083015182169084015260409182015116910152565b5060e0929092015180516001600160a01b0316610120830152602001516101409091015290565b60006020828403121561133957600080fd5b8151610afd81610b67565b634e487b7160e01b600052601160045260246000fd5b60006001820161136c5761136c611344565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261139857611398611373565b500490565b818103818111156113b0576113b0611344565b92915050565b6000826113c5576113c5611373565b500690565b808201808211156113b0576113b0611344565b87815260e0602082015260006113f660e0830189610b28565b63ffffffff881660408401526001600160a01b0387811660608501528616608084015284151560a084015282810360c08401526114338185610b28565b9a995050505050505050505056fea2646970667358221220d17954ba81bca52da6ca1f1cf74a0e04f2ce3c50651d1d806611eb18ab0d551e64736f6c63430008130033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80638c5f591a1461003b578063a3f4df7e14610050575b600080fd5b61004e610049366004610ac2565b610095565b005b61007f6040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b81525081565b60405161008c9190610b54565b60405180910390f35b600061009f6102cd565b905060008061015e6100b46020860186610b7f565b6100c16080870187610b9c565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506101039250505060a0880188610b9c565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610148925050506060890160408a01610b7f565b61015860408a0160208b01610b7f565b88610331565b909250905061017c6101766080860160608701610b7f565b836103c3565b60006101c361018e6020870187610b7f565b8461019c60c0890189610bf9565b856101ad60608b0160408c01610b7f565b6101bd60408c0160208d01610b7f565b8a610543565b50905060005b6101d660e0870187610c19565b9050811015610250576102466101ef6020880188610b7f565b836101fd60e08a018a610c19565b8581811061020d5761020d610c62565b905060200281019061021f9190610bf9565b8661023060608c0160408d01610b7f565b61024060408d0160208e01610b7f565b8b610543565b50506001016101c9565b5061025e6020860186610b7f565b6040516329287c1b60e21b8152600481018590523060248201523360448201526001600160a01b03919091169063a4a1f06c90606401600060405180830381600087803b1580156102ae57600080fd5b505af11580156102c2573d6000803e3d6000fd5b505050505050505050565b60008046905060006040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b815250823060405160200161031293929190610c78565b60408051601f1981840301815291905280516020909101209392505050565b600080876001600160a01b0316631a64dfad3089896040518463ffffffff1660e01b815260040161036493929190610cb1565b6020604051808303816000875af1158015610383573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a79190610ce7565b91506103b68585858b86610892565b9050965096945050505050565b604080516001808252818301909252600091816020015b60608152602001906001900390816103da57505060408051600180825281830190925291925060009190602082015b6060815260200190600190039081610409579050509050604051806040016040528060088152602001671d1bdc12185d125960c21b8152508260008151811061045457610454610c62565b602002602001018190525061046883610928565b8160008151811061047b5761047b610c62565b6020026020010181905250336001600160a01b031663468721a785600085856040516024016104ab929190610d6b565b60408051601f198184030181529181526020820180516001600160e01b031663579374b960e11b1790525160e085901b6001600160e01b03191681526104f993929190600090600401610d90565b6020604051808303816000875af1158015610518573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053c9190610df4565b5050505050565b60008061055a89896105548a61113b565b89610a30565b91506105698585858c86610892565b9050600061057d60a0890160808a01610b7f565b6001600160a01b03161461061d576001600160a01b03891663641f776e836105ab60a08b0160808c01610b7f565b6040516001600160e01b031960e085901b16815260048101929092526001600160a01b031660248201526044016020604051808303816000875af11580156105f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061b9190610df4565b505b60005b61062d60a08901896111ff565b905081101561088557600061064560a08a018a6111ff565b8381811061065557610655610c62565b9050610160020180360381019061066c9190611248565b6060810151815160408084015190516001600160a01b0390921660248301526001600160801b03166044820152919250339163468721a7919060009060640160408051601f198184030181529181526020820180516001600160e01b031663095ea7b360e01b1790525160e085901b6001600160e01b03191681526106f993929190600090600401610d90565b6020604051808303816000875af1158015610718573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073c9190610df4565b50600060405180610100016040528083602001516001600160a01b03168152602001856001600160a01b0316815260200183604001516001600160801b0316815260200183606001516001600160a01b031681526020018360800151151581526020018360a00151151581526020018360c0015181526020018360e001518152509050336001600160a01b031663468721a783600001516000846040516024016107e69190611265565b60408051601f198184030181529181526020820180516001600160e01b03166353b1572760e01b1790525160e085901b6001600160e01b031916815261083493929190600090600401610d90565b6020604051808303816000875af1158015610853573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108779190610df4565b508260010192505050610620565b5097509795505050505050565b604051638a54c52f60e01b81526001600160a01b0385811660048301526024820185905246604483015283811660648301526084820183905260009190871690638a54c52f9060a4016020604051808303816000875af11580156108fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091e9190611327565b9695505050505050565b60608160000361094f5750506040805180820190915260018152600360fc1b602082015290565b8160005b811561097957806109638161135a565b91506109729050600a83611389565b9150610953565b6000816001600160401b0381111561099357610993610d00565b6040519080825280601f01601f1916602001820160405280156109bd576020820181803683370190505b5090505b8415610a28576109d260018361139d565b91506109df600a866113b6565b6109ea9060306113ca565b60f81b8183815181106109ff576109ff610c62565b60200101906001600160f81b031916908160001a905350610a21600a86611389565b94506109c1565b949350505050565b6020820151825160608401516040808601519051635829492f60e11b81526000946001600160a01b038a169463b052925e94610a76948b948a92839290916004016113dd565b6020604051808303816000875af1158015610a95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab99190610ce7565b95945050505050565b600060208284031215610ad457600080fd5b81356001600160401b03811115610aea57600080fd5b82016101008185031215610afd57600080fd5b9392505050565b60005b83811015610b1f578181015183820152602001610b07565b50506000910152565b60008151808452610b40816020860160208601610b04565b601f01601f19169290920160200192915050565b602081526000610afd6020830184610b28565b6001600160a01b0381168114610b7c57600080fd5b50565b600060208284031215610b9157600080fd5b8135610afd81610b67565b6000808335601e19843603018112610bb357600080fd5b8301803591506001600160401b03821115610bcd57600080fd5b602001915036819003821315610be257600080fd5b9250929050565b8035610bf481610b67565b919050565b6000823560be19833603018112610c0f57600080fd5b9190910192915050565b6000808335601e19843603018112610c3057600080fd5b8301803591506001600160401b03821115610c4a57600080fd5b6020019150600581901b3603821315610be257600080fd5b634e487b7160e01b600052603260045260246000fd5b60008451610c8a818460208901610b04565b919091019283525060601b6bffffffffffffffffffffffff19166020820152603401919050565b6001600160a01b0384168152606060208201819052600090610cd590830185610b28565b828103604084015261091e8185610b28565b600060208284031215610cf957600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b600081518084526020808501808196508360051b8101915082860160005b85811015610d5e578284038952610d4c848351610b28565b98850198935090840190600101610d34565b5091979650505050505050565b604081526000610d7e6040830185610d16565b8281036020840152610ab98185610d16565b60018060a01b0385168152836020820152608060408201526000610db76080830185610b28565b905060028310610dd757634e487b7160e01b600052602160045260246000fd5b82606083015295945050505050565b8015158114610b7c57600080fd5b600060208284031215610e0657600080fd5b8151610afd81610de6565b60405160c081016001600160401b0381118282101715610e3357610e33610d00565b60405290565b604051601f8201601f191681016001600160401b0381118282101715610e6157610e61610d00565b604052919050565b803563ffffffff81168114610bf457600080fd5b600082601f830112610e8e57600080fd5b81356001600160401b03811115610ea757610ea7610d00565b610eba601f8201601f1916602001610e39565b818152846020838601011115610ecf57600080fd5b816020850160208301376000918101602001919091529392505050565b8035610bf481610de6565b80356001600160801b0381168114610bf457600080fd5b803564ffffffffff81168114610bf457600080fd5b600060608284031215610f3557600080fd5b604051606081018181106001600160401b0382111715610f5757610f57610d00565b604052905080610f6683610f0e565b8152610f7460208401610f0e565b6020820152610f8560408401610f0e565b60408201525092915050565b600060408284031215610fa357600080fd5b604051604081018181106001600160401b0382111715610fc557610fc5610d00565b6040529050808235610fd681610b67565b8152602092830135920191909152919050565b60006101608284031215610ffc57600080fd5b60405161010081018181106001600160401b038211171561101f5761101f610d00565b60405290508061102e83610be9565b815261103c60208401610be9565b602082015261104d60408401610ef7565b604082015261105e60608401610be9565b606082015261106f60808401610eec565b608082015261108060a08401610eec565b60a08201526110928460c08501610f23565b60c08201526110a5846101208501610f91565b60e08201525092915050565b600082601f8301126110c257600080fd5b813560206001600160401b038211156110dd576110dd610d00565b6110eb818360051b01610e39565b828152610160928302850182019282820191908785111561110b57600080fd5b8387015b8581101561112e576111218982610fe9565b845292840192810161110f565b5090979650505050505050565b600060c0823603121561114d57600080fd5b611155610e11565b61115e83610e69565b815260208301356001600160401b038082111561117a57600080fd5b61118636838701610e7d565b6020840152604085013591508082111561119f57600080fd5b6111ab36838701610e7d565b60408401526111bc60608601610eec565b60608401526111cd60808601610be9565b608084015260a08501359150808211156111e657600080fd5b506111f3368286016110b1565b60a08301525092915050565b6000808335601e1984360301811261121657600080fd5b8301803591506001600160401b0382111561123057600080fd5b602001915061016081023603821315610be257600080fd5b6000610160828403121561125b57600080fd5b610afd8383610fe9565b81516001600160a01b0390811682526020808401518216908301526040808401516001600160801b031690830152606080840151909116908201526080808301516101608301916112b99084018215159052565b5060a08301516112cd60a084018215159052565b5060c083015161130060c0840182805164ffffffffff908116835260208083015182169084015260409182015116910152565b5060e0929092015180516001600160a01b0316610120830152602001516101409091015290565b60006020828403121561133957600080fd5b8151610afd81610b67565b634e487b7160e01b600052601160045260246000fd5b60006001820161136c5761136c611344565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261139857611398611373565b500490565b818103818111156113b0576113b0611344565b92915050565b6000826113c5576113c5611373565b500690565b808201808211156113b0576113b0611344565b87815260e0602082015260006113f660e0830189610b28565b63ffffffff881660408401526001600160a01b0387811660608501528616608084015284151560a084015282810360c08401526114338185610b28565b9a995050505050505050505056fea2646970667358221220d17954ba81bca52da6ca1f1cf74a0e04f2ce3c50651d1d806611eb18ab0d551e64736f6c63430008130033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/mainnet/solcInputs/512807b5d71481c693c202ae23158904.json b/deployments/mainnet/solcInputs/512807b5d71481c693c202ae23158904.json new file mode 100644 index 00000000..0d0d55c8 --- /dev/null +++ b/deployments/mainnet/solcInputs/512807b5d71481c693c202ae23158904.json @@ -0,0 +1,59 @@ +{ + "language": "Solidity", + "sources": { + "@gnosis.pm/safe-contracts/contracts/common/Enum.sol": { + "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.0 <0.9.0;\n\n/// @title Enum - Collection of enums\n/// @author Richard Meissner - \ncontract Enum {\n enum Operation {Call, DelegateCall}\n}\n" + }, + "@gnosis.pm/zodiac/contracts/interfaces/IAvatar.sol": { + "content": "// SPDX-License-Identifier: LGPL-3.0-only\n\n/// @title Zodiac Avatar - A contract that manages modules that can execute transactions via this contract.\npragma solidity >=0.7.0 <0.9.0;\n\nimport \"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\";\n\ninterface IAvatar {\n event EnabledModule(address module);\n event DisabledModule(address module);\n event ExecutionFromModuleSuccess(address indexed module);\n event ExecutionFromModuleFailure(address indexed module);\n\n /// @dev Enables a module on the avatar.\n /// @notice Can only be called by the avatar.\n /// @notice Modules should be stored as a linked list.\n /// @notice Must emit EnabledModule(address module) if successful.\n /// @param module Module to be enabled.\n function enableModule(address module) external;\n\n /// @dev Disables a module on the avatar.\n /// @notice Can only be called by the avatar.\n /// @notice Must emit DisabledModule(address module) if successful.\n /// @param prevModule Address that pointed to the module to be removed in the linked list\n /// @param module Module to be removed.\n function disableModule(address prevModule, address module) external;\n\n /// @dev Allows a Module to execute a transaction.\n /// @notice Can only be called by an enabled module.\n /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.\n /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.\n /// @param to Destination address of module transaction.\n /// @param value Ether value of module transaction.\n /// @param data Data payload of module transaction.\n /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.\n function execTransactionFromModule(\n address to,\n uint256 value,\n bytes memory data,\n Enum.Operation operation\n ) external returns (bool success);\n\n /// @dev Allows a Module to execute a transaction and return data\n /// @notice Can only be called by an enabled module.\n /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.\n /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.\n /// @param to Destination address of module transaction.\n /// @param value Ether value of module transaction.\n /// @param data Data payload of module transaction.\n /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.\n function execTransactionFromModuleReturnData(\n address to,\n uint256 value,\n bytes memory data,\n Enum.Operation operation\n ) external returns (bool success, bytes memory returnData);\n\n /// @dev Returns if an module is enabled\n /// @return True if the module is enabled\n function isModuleEnabled(address module) external view returns (bool);\n\n /// @dev Returns array of modules.\n /// @param start Start of the page.\n /// @param pageSize Maximum number of modules that should be returned.\n /// @return array Array of modules.\n /// @return next Start of the next page.\n function getModulesPaginated(address start, uint256 pageSize)\n external\n view\n returns (address[] memory array, address next);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp >>= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n" + }, + "contracts/DecentHats_0_1_0.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity =0.8.19;\n\nimport {Enum} from \"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\";\nimport {IAvatar} from \"@gnosis.pm/zodiac/contracts/interfaces/IAvatar.sol\";\nimport {Strings} from \"@openzeppelin/contracts/utils/Strings.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {IERC6551Registry} from \"./interfaces/IERC6551Registry.sol\";\nimport {IHats} from \"./interfaces/hats/IHats.sol\";\nimport {ISablierV2LockupLinear} from \"./interfaces/sablier/ISablierV2LockupLinear.sol\";\nimport {LockupLinear} from \"./interfaces/sablier/LockupLinear.sol\";\n\ncontract DecentHats_0_1_0 {\n string public constant NAME = \"DecentHats_0_1_0\";\n\n struct SablierStreamParams {\n ISablierV2LockupLinear sablier;\n address sender;\n uint128 totalAmount;\n address asset;\n bool cancelable;\n bool transferable;\n LockupLinear.Timestamps timestamps;\n LockupLinear.Broker broker;\n }\n\n struct Hat {\n uint32 maxSupply;\n string details;\n string imageURI;\n bool isMutable;\n address wearer;\n SablierStreamParams[] sablierParams; // Optional Sablier stream parameters\n }\n\n struct CreateTreeParams {\n IHats hatsProtocol;\n address hatsAccountImplementation;\n IERC6551Registry registry;\n address keyValuePairs;\n string topHatDetails;\n string topHatImageURI;\n Hat adminHat;\n Hat[] hats;\n }\n\n function getSalt() internal view returns (bytes32 salt) {\n uint256 chainId;\n assembly {\n chainId := chainid()\n }\n\n bytes memory concatenatedSaltInput = abi.encodePacked(\n NAME,\n chainId,\n address(this)\n );\n\n salt = keccak256(concatenatedSaltInput);\n }\n\n function updateKeyValuePairs(\n address _keyValuePairs,\n uint256 topHatId\n ) internal {\n string[] memory keys = new string[](1);\n string[] memory values = new string[](1);\n keys[0] = \"topHatId\";\n values[0] = Strings.toString(topHatId);\n\n IAvatar(msg.sender).execTransactionFromModule(\n _keyValuePairs,\n 0,\n abi.encodeWithSignature(\n \"updateValues(string[],string[])\",\n keys,\n values\n ),\n Enum.Operation.Call\n );\n }\n\n function createHat(\n IHats _hatsProtocol,\n uint256 adminHatId,\n Hat memory _hat,\n address topHatAccount\n ) internal returns (uint256) {\n return\n _hatsProtocol.createHat(\n adminHatId,\n _hat.details,\n _hat.maxSupply,\n topHatAccount,\n topHatAccount,\n _hat.isMutable,\n _hat.imageURI\n );\n }\n\n function createAccount(\n IERC6551Registry _registry,\n address _hatsAccountImplementation,\n bytes32 salt,\n address protocolAddress,\n uint256 hatId\n ) internal returns (address) {\n return\n _registry.createAccount(\n _hatsAccountImplementation,\n salt,\n block.chainid,\n protocolAddress,\n hatId\n );\n }\n\n function createTopHatAndAccount(\n IHats _hatsProtocol,\n string memory _topHatDetails,\n string memory _topHatImageURI,\n IERC6551Registry _registry,\n address _hatsAccountImplementation,\n bytes32 salt\n ) internal returns (uint256 topHatId, address topHatAccount) {\n topHatId = _hatsProtocol.mintTopHat(\n address(this),\n _topHatDetails,\n _topHatImageURI\n );\n\n topHatAccount = createAccount(\n _registry,\n _hatsAccountImplementation,\n salt,\n address(_hatsProtocol),\n topHatId\n );\n }\n\n function createHatAndAccountAndMintAndStreams(\n IHats hatsProtocol,\n uint256 adminHatId,\n Hat calldata hat,\n address topHatAccount,\n IERC6551Registry registry,\n address hatsAccountImplementation,\n bytes32 salt\n ) internal returns (uint256 hatId, address accountAddress) {\n hatId = createHat(hatsProtocol, adminHatId, hat, topHatAccount);\n\n accountAddress = createAccount(\n registry,\n hatsAccountImplementation,\n salt,\n address(hatsProtocol),\n hatId\n );\n\n if (hat.wearer != address(0)) {\n hatsProtocol.mintHat(hatId, hat.wearer);\n }\n\n for (uint256 i = 0; i < hat.sablierParams.length; ) {\n SablierStreamParams memory sablierParams = hat.sablierParams[i];\n\n // Approve tokens for Sablier\n IAvatar(msg.sender).execTransactionFromModule(\n sablierParams.asset,\n 0,\n abi.encodeWithSignature(\n \"approve(address,uint256)\",\n address(sablierParams.sablier),\n sablierParams.totalAmount\n ),\n Enum.Operation.Call\n );\n\n LockupLinear.CreateWithTimestamps memory params = LockupLinear\n .CreateWithTimestamps({\n sender: sablierParams.sender,\n recipient: accountAddress,\n totalAmount: sablierParams.totalAmount,\n asset: IERC20(sablierParams.asset),\n cancelable: sablierParams.cancelable,\n transferable: sablierParams.transferable,\n timestamps: sablierParams.timestamps,\n broker: sablierParams.broker\n });\n\n // Proxy the Sablier call through IAvatar\n IAvatar(msg.sender).execTransactionFromModule(\n address(sablierParams.sablier),\n 0,\n abi.encodeWithSignature(\n \"createWithTimestamps((address,address,uint128,address,bool,bool,(uint40,uint40,uint40),(address,uint256)))\",\n params\n ),\n Enum.Operation.Call\n );\n\n unchecked {\n ++i;\n }\n }\n }\n\n function createAndDeclareTree(CreateTreeParams calldata params) public {\n bytes32 salt = getSalt();\n\n (uint256 topHatId, address topHatAccount) = createTopHatAndAccount(\n params.hatsProtocol,\n params.topHatDetails,\n params.topHatImageURI,\n params.registry,\n params.hatsAccountImplementation,\n salt\n );\n\n updateKeyValuePairs(params.keyValuePairs, topHatId);\n\n (uint256 adminHatId, ) = createHatAndAccountAndMintAndStreams(\n params.hatsProtocol,\n topHatId,\n params.adminHat,\n topHatAccount,\n params.registry,\n params.hatsAccountImplementation,\n salt\n );\n\n for (uint256 i = 0; i < params.hats.length; ) {\n createHatAndAccountAndMintAndStreams(\n params.hatsProtocol,\n adminHatId,\n params.hats[i],\n topHatAccount,\n params.registry,\n params.hatsAccountImplementation,\n salt\n );\n\n unchecked {\n ++i;\n }\n }\n\n params.hatsProtocol.transferHat(topHatId, address(this), msg.sender);\n }\n}\n" + }, + "contracts/interfaces/hats/IHats.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0\n// Copyright (C) 2023 Haberdasher Labs\n//\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU Affero General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU Affero General Public License for more details.\n//\n// You should have received a copy of the GNU Affero General Public License\n// along with this program. If not, see .\n\npragma solidity >=0.8.13;\n\ninterface IHats {\n function mintTopHat(\n address _target,\n string memory _details,\n string memory _imageURI\n ) external returns (uint256 topHatId);\n\n function createHat(\n uint256 _admin,\n string calldata _details,\n uint32 _maxSupply,\n address _eligibility,\n address _toggle,\n bool _mutable,\n string calldata _imageURI\n ) external returns (uint256 newHatId);\n\n function mintHat(\n uint256 _hatId,\n address _wearer\n ) external returns (bool success);\n\n function transferHat(uint256 _hatId, address _from, address _to) external;\n}\n" + }, + "contracts/interfaces/IERC6551Registry.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\ninterface IERC6551Registry {\n /**\n * @dev Creates a token bound account for a non-fungible token.\n *\n * If account has already been created, returns the account address without calling create2.\n *\n * Emits ERC6551AccountCreated event.\n *\n * @return account The address of the token bound account\n */\n function createAccount(\n address implementation,\n bytes32 salt,\n uint256 chainId,\n address tokenContract,\n uint256 tokenId\n ) external returns (address account);\n}\n" + }, + "contracts/interfaces/sablier/ISablierV2LockupLinear.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {LockupLinear} from \"./LockupLinear.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface ISablierV2LockupLinear {\n function createWithTimestamps(\n LockupLinear.CreateWithTimestamps calldata params\n ) external returns (uint256 streamId);\n}\n" + }, + "contracts/interfaces/sablier/LockupLinear.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LockupLinear {\n struct CreateWithTimestamps {\n address sender;\n address recipient;\n uint128 totalAmount;\n IERC20 asset;\n bool cancelable;\n bool transferable;\n Timestamps timestamps;\n Broker broker;\n }\n\n struct Timestamps {\n uint40 start;\n uint40 cliff;\n uint40 end;\n }\n\n struct Broker {\n address account;\n uint256 fee;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/deployments/optimism/DecentHats_0_1_0.json b/deployments/optimism/DecentHats_0_1_0.json index f5a7e4b2..8b6d7e5f 100644 --- a/deployments/optimism/DecentHats_0_1_0.json +++ b/deployments/optimism/DecentHats_0_1_0.json @@ -1,5 +1,5 @@ { - "address": "0x47aB70e4e8E8e957c6373Ade97dE224a46b89896", + "address": "0xfEFe8C7E647E66D1612Aea29f9A58172823473E0", "abi": [ { "inputs": [], @@ -74,6 +74,82 @@ "internalType": "address", "name": "wearer", "type": "address" + }, + { + "components": [ + { + "internalType": "contract ISablierV2LockupLinear", + "name": "sablier", + "type": "address" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint128", + "name": "totalAmount", + "type": "uint128" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "bool", + "name": "cancelable", + "type": "bool" + }, + { + "internalType": "bool", + "name": "transferable", + "type": "bool" + }, + { + "components": [ + { + "internalType": "uint40", + "name": "start", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "cliff", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "end", + "type": "uint40" + } + ], + "internalType": "struct LockupLinear.Timestamps", + "name": "timestamps", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "fee", + "type": "uint256" + } + ], + "internalType": "struct LockupLinear.Broker", + "name": "broker", + "type": "tuple" + } + ], + "internalType": "struct DecentHats_0_1_0.SablierStreamParams[]", + "name": "sablierParams", + "type": "tuple[]" } ], "internalType": "struct DecentHats_0_1_0.Hat", @@ -106,6 +182,82 @@ "internalType": "address", "name": "wearer", "type": "address" + }, + { + "components": [ + { + "internalType": "contract ISablierV2LockupLinear", + "name": "sablier", + "type": "address" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint128", + "name": "totalAmount", + "type": "uint128" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "bool", + "name": "cancelable", + "type": "bool" + }, + { + "internalType": "bool", + "name": "transferable", + "type": "bool" + }, + { + "components": [ + { + "internalType": "uint40", + "name": "start", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "cliff", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "end", + "type": "uint40" + } + ], + "internalType": "struct LockupLinear.Timestamps", + "name": "timestamps", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "fee", + "type": "uint256" + } + ], + "internalType": "struct LockupLinear.Broker", + "name": "broker", + "type": "tuple" + } + ], + "internalType": "struct DecentHats_0_1_0.SablierStreamParams[]", + "name": "sablierParams", + "type": "tuple[]" } ], "internalType": "struct DecentHats_0_1_0.Hat[]", @@ -124,28 +276,28 @@ "type": "function" } ], - "transactionHash": "0xc233a086c255dd869cf5603a36813fd9c4ed9f75506291308e6d6afe1458333a", + "transactionHash": "0x2e4fa7b47997c07b811a519aed15ce4cd26a4ee4f653171df17b5b62177252d5", "receipt": { "to": null, "from": "0xb5Ca125166C1987A35EDD550E16846Fa1e1D9bB3", - "contractAddress": "0x47aB70e4e8E8e957c6373Ade97dE224a46b89896", - "transactionIndex": 5, - "gasUsed": "848547", + "contractAddress": "0xfEFe8C7E647E66D1612Aea29f9A58172823473E0", + "transactionIndex": 6, + "gasUsed": "1184549", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x1ec7c4a8d15c415c0b31cad90e5ec3a12fc1e9f570d2023509a793e936ef032d", - "transactionHash": "0xc233a086c255dd869cf5603a36813fd9c4ed9f75506291308e6d6afe1458333a", + "blockHash": "0x91e1a70dbf0793305c67cd6aed401ea9707a0429f7900dd0bb235e77e351d7b6", + "transactionHash": "0x2e4fa7b47997c07b811a519aed15ce4cd26a4ee4f653171df17b5b62177252d5", "logs": [], - "blockNumber": 122496501, - "cumulativeGasUsed": "1334590", + "blockNumber": 125243972, + "cumulativeGasUsed": "2509623", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "88a7dc38a4aa54f89c0bd740dfe90545", - "metadata": "{\"compiler\":{\"version\":\"0.8.19+commit.7dd6d404\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"NAME\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contract IHats\",\"name\":\"hatsProtocol\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"hatsAccountImplementation\",\"type\":\"address\"},{\"internalType\":\"contract IERC6551Registry\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"keyValuePairs\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"topHatDetails\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"topHatImageURI\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxSupply\",\"type\":\"uint32\"},{\"internalType\":\"string\",\"name\":\"details\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"imageURI\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isMutable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"wearer\",\"type\":\"address\"}],\"internalType\":\"struct DecentHats_0_1_0.Hat\",\"name\":\"adminHat\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxSupply\",\"type\":\"uint32\"},{\"internalType\":\"string\",\"name\":\"details\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"imageURI\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isMutable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"wearer\",\"type\":\"address\"}],\"internalType\":\"struct DecentHats_0_1_0.Hat[]\",\"name\":\"hats\",\"type\":\"tuple[]\"}],\"internalType\":\"struct DecentHats_0_1_0.CreateTreeParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"createAndDeclareTree\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/DecentHats_0_1_0.sol\":\"DecentHats_0_1_0\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.7.0 <0.9.0;\\n\\n/// @title Enum - Collection of enums\\n/// @author Richard Meissner - \\ncontract Enum {\\n enum Operation {Call, DelegateCall}\\n}\\n\",\"keccak256\":\"0x473e45b1a5cc47be494b0e123c9127f0c11c1e0992a321ae5a644c0bfdb2c14f\",\"license\":\"LGPL-3.0-only\"},\"@gnosis.pm/zodiac/contracts/interfaces/IAvatar.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\n\\n/// @title Zodiac Avatar - A contract that manages modules that can execute transactions via this contract.\\npragma solidity >=0.7.0 <0.9.0;\\n\\nimport \\\"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\\\";\\n\\ninterface IAvatar {\\n event EnabledModule(address module);\\n event DisabledModule(address module);\\n event ExecutionFromModuleSuccess(address indexed module);\\n event ExecutionFromModuleFailure(address indexed module);\\n\\n /// @dev Enables a module on the avatar.\\n /// @notice Can only be called by the avatar.\\n /// @notice Modules should be stored as a linked list.\\n /// @notice Must emit EnabledModule(address module) if successful.\\n /// @param module Module to be enabled.\\n function enableModule(address module) external;\\n\\n /// @dev Disables a module on the avatar.\\n /// @notice Can only be called by the avatar.\\n /// @notice Must emit DisabledModule(address module) if successful.\\n /// @param prevModule Address that pointed to the module to be removed in the linked list\\n /// @param module Module to be removed.\\n function disableModule(address prevModule, address module) external;\\n\\n /// @dev Allows a Module to execute a transaction.\\n /// @notice Can only be called by an enabled module.\\n /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.\\n /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.\\n /// @param to Destination address of module transaction.\\n /// @param value Ether value of module transaction.\\n /// @param data Data payload of module transaction.\\n /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.\\n function execTransactionFromModule(\\n address to,\\n uint256 value,\\n bytes memory data,\\n Enum.Operation operation\\n ) external returns (bool success);\\n\\n /// @dev Allows a Module to execute a transaction and return data\\n /// @notice Can only be called by an enabled module.\\n /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.\\n /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.\\n /// @param to Destination address of module transaction.\\n /// @param value Ether value of module transaction.\\n /// @param data Data payload of module transaction.\\n /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.\\n function execTransactionFromModuleReturnData(\\n address to,\\n uint256 value,\\n bytes memory data,\\n Enum.Operation operation\\n ) external returns (bool success, bytes memory returnData);\\n\\n /// @dev Returns if an module is enabled\\n /// @return True if the module is enabled\\n function isModuleEnabled(address module) external view returns (bool);\\n\\n /// @dev Returns array of modules.\\n /// @param start Start of the page.\\n /// @param pageSize Maximum number of modules that should be returned.\\n /// @return array Array of modules.\\n /// @return next Start of the next page.\\n function getModulesPaginated(address start, uint256 pageSize)\\n external\\n view\\n returns (address[] memory array, address next);\\n}\\n\",\"keccak256\":\"0xcd5508ffe596eef8fbccfd5fc4f10a34397773547ce64e212d48b5212865ec1f\",\"license\":\"LGPL-3.0-only\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n}\\n\",\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\"},\"contracts/DecentHats_0_1_0.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity =0.8.19;\\n\\nimport {Enum} from \\\"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\\\";\\nimport {IAvatar} from \\\"@gnosis.pm/zodiac/contracts/interfaces/IAvatar.sol\\\";\\nimport {Strings} from \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\nimport {IERC6551Registry} from \\\"./interfaces/IERC6551Registry.sol\\\";\\nimport {IHats} from \\\"./interfaces/hats/IHats.sol\\\";\\n\\ncontract DecentHats_0_1_0 {\\n string public constant NAME = \\\"DecentHats_0_1_0\\\";\\n\\n struct Hat {\\n uint32 maxSupply;\\n string details;\\n string imageURI;\\n bool isMutable;\\n address wearer;\\n }\\n\\n struct CreateTreeParams {\\n IHats hatsProtocol;\\n address hatsAccountImplementation;\\n IERC6551Registry registry;\\n address keyValuePairs;\\n string topHatDetails;\\n string topHatImageURI;\\n Hat adminHat;\\n Hat[] hats;\\n }\\n\\n function getSalt() internal view returns (bytes32 salt) {\\n uint256 chainId;\\n assembly {\\n chainId := chainid()\\n }\\n\\n bytes memory concatenatedSaltInput = abi.encodePacked(\\n NAME,\\n chainId,\\n address(this)\\n );\\n\\n salt = keccak256(concatenatedSaltInput);\\n }\\n\\n function createTopHat(\\n IHats _hatsProtocol,\\n string memory _topHatDetails,\\n string memory _topHatImageURI\\n ) internal returns (uint256) {\\n return\\n _hatsProtocol.mintTopHat(\\n address(this),\\n _topHatDetails,\\n _topHatImageURI\\n );\\n }\\n\\n function createAccount(\\n IERC6551Registry _registry,\\n address _hatsAccountImplementation,\\n bytes32 salt,\\n address protocolAddress,\\n uint256 hatId\\n ) internal returns (address) {\\n return\\n _registry.createAccount(\\n _hatsAccountImplementation,\\n salt,\\n block.chainid,\\n protocolAddress,\\n hatId\\n );\\n }\\n\\n function updateKeyValuePairs(\\n address _keyValuePairs,\\n uint256 topHatId\\n ) internal {\\n string[] memory keys = new string[](1);\\n string[] memory values = new string[](1);\\n keys[0] = \\\"topHatId\\\";\\n values[0] = Strings.toString(topHatId);\\n\\n IAvatar(msg.sender).execTransactionFromModule(\\n _keyValuePairs,\\n 0,\\n abi.encodeWithSignature(\\n \\\"updateValues(string[],string[])\\\",\\n keys,\\n values\\n ),\\n Enum.Operation.Call\\n );\\n }\\n\\n function createHat(\\n IHats _hatsProtocol,\\n uint256 adminHatId,\\n Hat memory _hat,\\n address topHatAccount\\n ) internal returns (uint256) {\\n return\\n _hatsProtocol.createHat(\\n adminHatId,\\n _hat.details,\\n _hat.maxSupply,\\n topHatAccount,\\n topHatAccount,\\n _hat.isMutable,\\n _hat.imageURI\\n );\\n }\\n\\n function createHatAccountMint(\\n IHats hatsProtocol,\\n uint256 adminHatId,\\n Hat calldata hat,\\n address topHatAccount,\\n IERC6551Registry registry,\\n address hatsAccountImplementation,\\n bytes32 salt\\n ) internal returns (uint256 hatId, address accountAddress) {\\n hatId = createHat(hatsProtocol, adminHatId, hat, topHatAccount);\\n\\n accountAddress = createAccount(\\n registry,\\n hatsAccountImplementation,\\n salt,\\n address(hatsProtocol),\\n hatId\\n );\\n\\n if (hat.wearer != address(0)) {\\n hatsProtocol.mintHat(hatId, hat.wearer);\\n }\\n }\\n\\n function handleHats(\\n IHats _hatsProtocol,\\n IERC6551Registry _registry,\\n address _hatsAccountImplementation,\\n bytes32 salt,\\n address topHatAccount,\\n uint256 adminHatId,\\n Hat[] calldata _hats\\n ) internal {\\n for (uint256 i = 0; i < _hats.length; ) {\\n createHatAccountMint(\\n _hatsProtocol,\\n adminHatId,\\n _hats[i],\\n topHatAccount,\\n _registry,\\n _hatsAccountImplementation,\\n salt\\n );\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n function createAndDeclareTree(CreateTreeParams calldata params) public {\\n bytes32 salt = getSalt();\\n uint256 topHatId = createTopHat(\\n params.hatsProtocol,\\n params.topHatDetails,\\n params.topHatImageURI\\n );\\n address topHatAccount = createAccount(\\n params.registry,\\n params.hatsAccountImplementation,\\n salt,\\n address(params.hatsProtocol),\\n topHatId\\n );\\n\\n updateKeyValuePairs(params.keyValuePairs, topHatId);\\n\\n (uint256 adminHatId, ) = createHatAccountMint(\\n params.hatsProtocol,\\n topHatId,\\n params.adminHat,\\n topHatAccount,\\n params.registry,\\n params.hatsAccountImplementation,\\n salt\\n );\\n\\n handleHats(\\n params.hatsProtocol,\\n params.registry,\\n params.hatsAccountImplementation,\\n salt,\\n topHatAccount,\\n adminHatId,\\n params.hats\\n );\\n\\n params.hatsProtocol.transferHat(topHatId, address(this), msg.sender);\\n }\\n}\\n\",\"keccak256\":\"0xd7dbbda48b0f7eedeef3882aab51e93c4881a47bcb09b2f9a20989d22259f027\",\"license\":\"MIT\"},\"contracts/interfaces/IERC6551Registry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IERC6551Registry {\\n /**\\n * @dev Creates a token bound account for a non-fungible token.\\n *\\n * If account has already been created, returns the account address without calling create2.\\n *\\n * Emits ERC6551AccountCreated event.\\n *\\n * @return account The address of the token bound account\\n */\\n function createAccount(\\n address implementation,\\n bytes32 salt,\\n uint256 chainId,\\n address tokenContract,\\n uint256 tokenId\\n ) external returns (address account);\\n}\\n\",\"keccak256\":\"0x64c52de8a8e68398e61dd8b42dda8e9af8cf6abf93bb85629c322440991ea568\",\"license\":\"MIT\"},\"contracts/interfaces/hats/IHats.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0\\n// Copyright (C) 2023 Haberdasher Labs\\n//\\n// This program is free software: you can redistribute it and/or modify\\n// it under the terms of the GNU Affero General Public License as published by\\n// the Free Software Foundation, either version 3 of the License, or\\n// (at your option) any later version.\\n//\\n// This program is distributed in the hope that it will be useful,\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\\n// GNU Affero General Public License for more details.\\n//\\n// You should have received a copy of the GNU Affero General Public License\\n// along with this program. If not, see .\\n\\npragma solidity >=0.8.13;\\n\\ninterface IHats {\\n function mintTopHat(\\n address _target,\\n string memory _details,\\n string memory _imageURI\\n ) external returns (uint256 topHatId);\\n\\n function createHat(\\n uint256 _admin,\\n string calldata _details,\\n uint32 _maxSupply,\\n address _eligibility,\\n address _toggle,\\n bool _mutable,\\n string calldata _imageURI\\n ) external returns (uint256 newHatId);\\n\\n function mintHat(\\n uint256 _hatId,\\n address _wearer\\n ) external returns (bool success);\\n\\n function transferHat(uint256 _hatId, address _from, address _to) external;\\n}\\n\",\"keccak256\":\"0x8e35022f5c0fcf0059033abec78ec890f0cf3bbac09d6d24051cff9679239511\",\"license\":\"AGPL-3.0\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50610e63806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063a3f4df7e1461003b578063c1bce50714610080575b600080fd5b61006a6040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b81525081565b60405161007791906108a5565b60405180910390f35b61009361008e3660046108bf565b610095565b005b600061009f61029d565b9050600061013c6100b36020850185610913565b6100c06080860186610930565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506101029250505060a0870187610930565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061030192505050565b905060006101776101536060860160408701610913565b6101636040870160208801610913565b856101716020890189610913565b8661037f565b905061019261018c6080860160608701610913565b83610415565b60006101d96101a46020870187610913565b846101b260c089018961098e565b856101c360608b0160408c01610913565b6101d360408c0160208d01610913565b8a610595565b5090506102216101ec6020870187610913565b6101fc6060880160408901610913565b61020c6040890160208a01610913565b87868661021c60e08d018d6109ae565b61067b565b61022e6020860186610913565b6040516329287c1b60e21b8152600481018590523060248201523360448201526001600160a01b03919091169063a4a1f06c90606401600060405180830381600087803b15801561027e57600080fd5b505af1158015610292573d6000803e3d6000fd5b505050505050505050565b60008046905060006040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b81525082306040516020016102e2939291906109f8565b60408051601f1981840301815291905280516020909101209392505050565b604051631a64dfad60e01b81526000906001600160a01b03851690631a64dfad9061033490309087908790600401610a31565b6020604051808303816000875af1158015610353573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103779190610a67565b949350505050565b604051638a54c52f60e01b81526001600160a01b0385811660048301526024820185905246604483015283811660648301526084820183905260009190871690638a54c52f9060a4016020604051808303816000875af11580156103e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061040b9190610a80565b9695505050505050565b604080516001808252818301909252600091816020015b606081526020019060019003908161042c57505060408051600180825281830190925291925060009190602082015b606081526020019060019003908161045b579050509050604051806040016040528060088152602001671d1bdc12185d125960c21b815250826000815181106104a6576104a6610ab3565b60200260200101819052506104ba836106c2565b816000815181106104cd576104cd610ab3565b6020026020010181905250336001600160a01b031663468721a785600085856040516024016104fd929190610b1e565b60408051601f198184030181529181526020820180516001600160e01b031663579374b960e11b1790525160e085901b6001600160e01b031916815261054b93929190600090600401610b43565b6020604051808303816000875af115801561056a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058e9190610ba7565b5050505050565b6000806105ac89896105a68a610c85565b896107c3565b91506105bb8585858c8661037f565b905060006105cf60a0890160808a01610913565b6001600160a01b03161461066f576001600160a01b03891663641f776e836105fd60a08b0160808c01610913565b6040516001600160e01b031960e085901b16815260048101929092526001600160a01b031660248201526044016020604051808303816000875af1158015610649573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066d9190610ba7565b505b97509795505050505050565b60005b81811015610292576106b8898585858581811061069d5761069d610ab3565b90506020028101906106af919061098e565b888c8c8c610595565b505060010161067e565b6060816000036106e95750506040805180820190915260018152600360fc1b602082015290565b8160005b811561071357806106fd81610d46565b915061070c9050600a83610d75565b91506106ed565b60008167ffffffffffffffff81111561072e5761072e610a9d565b6040519080825280601f01601f191660200182016040528015610758576020820181803683370190505b5090505b84156103775761076d600183610d89565b915061077a600a86610da2565b610785906030610db6565b60f81b81838151811061079a5761079a610ab3565b60200101906001600160f81b031916908160001a9053506107bc600a86610d75565b945061075c565b6020820151825160608401516040808601519051635829492f60e11b81526000946001600160a01b038a169463b052925e94610809948b948a9283929091600401610dc9565b6020604051808303816000875af1158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c9190610a67565b95945050505050565b60005b83811015610870578181015183820152602001610858565b50506000910152565b60008151808452610891816020860160208601610855565b601f01601f19169290920160200192915050565b6020815260006108b86020830184610879565b9392505050565b6000602082840312156108d157600080fd5b813567ffffffffffffffff8111156108e857600080fd5b820161010081850312156108b857600080fd5b6001600160a01b038116811461091057600080fd5b50565b60006020828403121561092557600080fd5b81356108b8816108fb565b6000808335601e1984360301811261094757600080fd5b83018035915067ffffffffffffffff82111561096257600080fd5b60200191503681900382131561097757600080fd5b9250929050565b8035610989816108fb565b919050565b60008235609e198336030181126109a457600080fd5b9190910192915050565b6000808335601e198436030181126109c557600080fd5b83018035915067ffffffffffffffff8211156109e057600080fd5b6020019150600581901b360382131561097757600080fd5b60008451610a0a818460208901610855565b919091019283525060601b6bffffffffffffffffffffffff19166020820152603401919050565b6001600160a01b0384168152606060208201819052600090610a5590830185610879565b828103604084015261040b8185610879565b600060208284031215610a7957600080fd5b5051919050565b600060208284031215610a9257600080fd5b81516108b8816108fb565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501808196508360051b8101915082860160005b85811015610b11578284038952610aff848351610879565b98850198935090840190600101610ae7565b5091979650505050505050565b604081526000610b316040830185610ac9565b828103602084015261084c8185610ac9565b60018060a01b0385168152836020820152608060408201526000610b6a6080830185610879565b905060028310610b8a57634e487b7160e01b600052602160045260246000fd5b82606083015295945050505050565b801515811461091057600080fd5b600060208284031215610bb957600080fd5b81516108b881610b99565b60405160a0810167ffffffffffffffff81118282101715610be757610be7610a9d565b60405290565b600082601f830112610bfe57600080fd5b813567ffffffffffffffff80821115610c1957610c19610a9d565b604051601f8301601f19908116603f01168101908282118183101715610c4157610c41610a9d565b81604052838152866020858801011115610c5a57600080fd5b836020870160208301376000602085830101528094505050505092915050565b803561098981610b99565b600060a08236031215610c9757600080fd5b610c9f610bc4565b823563ffffffff81168114610cb357600080fd5b8152602083013567ffffffffffffffff80821115610cd057600080fd5b610cdc36838701610bed565b60208401526040850135915080821115610cf557600080fd5b50610d0236828601610bed565b604083015250610d1460608401610c7a565b6060820152610d256080840161097e565b608082015292915050565b634e487b7160e01b600052601160045260246000fd5b600060018201610d5857610d58610d30565b5060010190565b634e487b7160e01b600052601260045260246000fd5b600082610d8457610d84610d5f565b500490565b81810381811115610d9c57610d9c610d30565b92915050565b600082610db157610db1610d5f565b500690565b80820180821115610d9c57610d9c610d30565b87815260e060208201526000610de260e0830189610879565b63ffffffff881660408401526001600160a01b0387811660608501528616608084015284151560a084015282810360c0840152610e1f8185610879565b9a995050505050505050505056fea264697066735822122040470770e7f603d20cdea8118401756a0349e1cdc776519095ccf844ef03c2cd64736f6c63430008130033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c8063a3f4df7e1461003b578063c1bce50714610080575b600080fd5b61006a6040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b81525081565b60405161007791906108a5565b60405180910390f35b61009361008e3660046108bf565b610095565b005b600061009f61029d565b9050600061013c6100b36020850185610913565b6100c06080860186610930565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506101029250505060a0870187610930565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061030192505050565b905060006101776101536060860160408701610913565b6101636040870160208801610913565b856101716020890189610913565b8661037f565b905061019261018c6080860160608701610913565b83610415565b60006101d96101a46020870187610913565b846101b260c089018961098e565b856101c360608b0160408c01610913565b6101d360408c0160208d01610913565b8a610595565b5090506102216101ec6020870187610913565b6101fc6060880160408901610913565b61020c6040890160208a01610913565b87868661021c60e08d018d6109ae565b61067b565b61022e6020860186610913565b6040516329287c1b60e21b8152600481018590523060248201523360448201526001600160a01b03919091169063a4a1f06c90606401600060405180830381600087803b15801561027e57600080fd5b505af1158015610292573d6000803e3d6000fd5b505050505050505050565b60008046905060006040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b81525082306040516020016102e2939291906109f8565b60408051601f1981840301815291905280516020909101209392505050565b604051631a64dfad60e01b81526000906001600160a01b03851690631a64dfad9061033490309087908790600401610a31565b6020604051808303816000875af1158015610353573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103779190610a67565b949350505050565b604051638a54c52f60e01b81526001600160a01b0385811660048301526024820185905246604483015283811660648301526084820183905260009190871690638a54c52f9060a4016020604051808303816000875af11580156103e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061040b9190610a80565b9695505050505050565b604080516001808252818301909252600091816020015b606081526020019060019003908161042c57505060408051600180825281830190925291925060009190602082015b606081526020019060019003908161045b579050509050604051806040016040528060088152602001671d1bdc12185d125960c21b815250826000815181106104a6576104a6610ab3565b60200260200101819052506104ba836106c2565b816000815181106104cd576104cd610ab3565b6020026020010181905250336001600160a01b031663468721a785600085856040516024016104fd929190610b1e565b60408051601f198184030181529181526020820180516001600160e01b031663579374b960e11b1790525160e085901b6001600160e01b031916815261054b93929190600090600401610b43565b6020604051808303816000875af115801561056a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058e9190610ba7565b5050505050565b6000806105ac89896105a68a610c85565b896107c3565b91506105bb8585858c8661037f565b905060006105cf60a0890160808a01610913565b6001600160a01b03161461066f576001600160a01b03891663641f776e836105fd60a08b0160808c01610913565b6040516001600160e01b031960e085901b16815260048101929092526001600160a01b031660248201526044016020604051808303816000875af1158015610649573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066d9190610ba7565b505b97509795505050505050565b60005b81811015610292576106b8898585858581811061069d5761069d610ab3565b90506020028101906106af919061098e565b888c8c8c610595565b505060010161067e565b6060816000036106e95750506040805180820190915260018152600360fc1b602082015290565b8160005b811561071357806106fd81610d46565b915061070c9050600a83610d75565b91506106ed565b60008167ffffffffffffffff81111561072e5761072e610a9d565b6040519080825280601f01601f191660200182016040528015610758576020820181803683370190505b5090505b84156103775761076d600183610d89565b915061077a600a86610da2565b610785906030610db6565b60f81b81838151811061079a5761079a610ab3565b60200101906001600160f81b031916908160001a9053506107bc600a86610d75565b945061075c565b6020820151825160608401516040808601519051635829492f60e11b81526000946001600160a01b038a169463b052925e94610809948b948a9283929091600401610dc9565b6020604051808303816000875af1158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c9190610a67565b95945050505050565b60005b83811015610870578181015183820152602001610858565b50506000910152565b60008151808452610891816020860160208601610855565b601f01601f19169290920160200192915050565b6020815260006108b86020830184610879565b9392505050565b6000602082840312156108d157600080fd5b813567ffffffffffffffff8111156108e857600080fd5b820161010081850312156108b857600080fd5b6001600160a01b038116811461091057600080fd5b50565b60006020828403121561092557600080fd5b81356108b8816108fb565b6000808335601e1984360301811261094757600080fd5b83018035915067ffffffffffffffff82111561096257600080fd5b60200191503681900382131561097757600080fd5b9250929050565b8035610989816108fb565b919050565b60008235609e198336030181126109a457600080fd5b9190910192915050565b6000808335601e198436030181126109c557600080fd5b83018035915067ffffffffffffffff8211156109e057600080fd5b6020019150600581901b360382131561097757600080fd5b60008451610a0a818460208901610855565b919091019283525060601b6bffffffffffffffffffffffff19166020820152603401919050565b6001600160a01b0384168152606060208201819052600090610a5590830185610879565b828103604084015261040b8185610879565b600060208284031215610a7957600080fd5b5051919050565b600060208284031215610a9257600080fd5b81516108b8816108fb565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501808196508360051b8101915082860160005b85811015610b11578284038952610aff848351610879565b98850198935090840190600101610ae7565b5091979650505050505050565b604081526000610b316040830185610ac9565b828103602084015261084c8185610ac9565b60018060a01b0385168152836020820152608060408201526000610b6a6080830185610879565b905060028310610b8a57634e487b7160e01b600052602160045260246000fd5b82606083015295945050505050565b801515811461091057600080fd5b600060208284031215610bb957600080fd5b81516108b881610b99565b60405160a0810167ffffffffffffffff81118282101715610be757610be7610a9d565b60405290565b600082601f830112610bfe57600080fd5b813567ffffffffffffffff80821115610c1957610c19610a9d565b604051601f8301601f19908116603f01168101908282118183101715610c4157610c41610a9d565b81604052838152866020858801011115610c5a57600080fd5b836020870160208301376000602085830101528094505050505092915050565b803561098981610b99565b600060a08236031215610c9757600080fd5b610c9f610bc4565b823563ffffffff81168114610cb357600080fd5b8152602083013567ffffffffffffffff80821115610cd057600080fd5b610cdc36838701610bed565b60208401526040850135915080821115610cf557600080fd5b50610d0236828601610bed565b604083015250610d1460608401610c7a565b6060820152610d256080840161097e565b608082015292915050565b634e487b7160e01b600052601160045260246000fd5b600060018201610d5857610d58610d30565b5060010190565b634e487b7160e01b600052601260045260246000fd5b600082610d8457610d84610d5f565b500490565b81810381811115610d9c57610d9c610d30565b92915050565b600082610db157610db1610d5f565b500690565b80820180821115610d9c57610d9c610d30565b87815260e060208201526000610de260e0830189610879565b63ffffffff881660408401526001600160a01b0387811660608501528616608084015284151560a084015282810360c0840152610e1f8185610879565b9a995050505050505050505056fea264697066735822122040470770e7f603d20cdea8118401756a0349e1cdc776519095ccf844ef03c2cd64736f6c63430008130033", + "numDeployments": 2, + "solcInputHash": "512807b5d71481c693c202ae23158904", + "metadata": "{\"compiler\":{\"version\":\"0.8.19+commit.7dd6d404\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"NAME\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contract IHats\",\"name\":\"hatsProtocol\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"hatsAccountImplementation\",\"type\":\"address\"},{\"internalType\":\"contract IERC6551Registry\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"keyValuePairs\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"topHatDetails\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"topHatImageURI\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxSupply\",\"type\":\"uint32\"},{\"internalType\":\"string\",\"name\":\"details\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"imageURI\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isMutable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"wearer\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"contract ISablierV2LockupLinear\",\"name\":\"sablier\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint128\",\"name\":\"totalAmount\",\"type\":\"uint128\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"cancelable\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"transferable\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"uint40\",\"name\":\"start\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"cliff\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"end\",\"type\":\"uint40\"}],\"internalType\":\"struct LockupLinear.Timestamps\",\"name\":\"timestamps\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"}],\"internalType\":\"struct LockupLinear.Broker\",\"name\":\"broker\",\"type\":\"tuple\"}],\"internalType\":\"struct DecentHats_0_1_0.SablierStreamParams[]\",\"name\":\"sablierParams\",\"type\":\"tuple[]\"}],\"internalType\":\"struct DecentHats_0_1_0.Hat\",\"name\":\"adminHat\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxSupply\",\"type\":\"uint32\"},{\"internalType\":\"string\",\"name\":\"details\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"imageURI\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isMutable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"wearer\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"contract ISablierV2LockupLinear\",\"name\":\"sablier\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint128\",\"name\":\"totalAmount\",\"type\":\"uint128\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"cancelable\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"transferable\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"uint40\",\"name\":\"start\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"cliff\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"end\",\"type\":\"uint40\"}],\"internalType\":\"struct LockupLinear.Timestamps\",\"name\":\"timestamps\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"}],\"internalType\":\"struct LockupLinear.Broker\",\"name\":\"broker\",\"type\":\"tuple\"}],\"internalType\":\"struct DecentHats_0_1_0.SablierStreamParams[]\",\"name\":\"sablierParams\",\"type\":\"tuple[]\"}],\"internalType\":\"struct DecentHats_0_1_0.Hat[]\",\"name\":\"hats\",\"type\":\"tuple[]\"}],\"internalType\":\"struct DecentHats_0_1_0.CreateTreeParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"createAndDeclareTree\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/DecentHats_0_1_0.sol\":\"DecentHats_0_1_0\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.7.0 <0.9.0;\\n\\n/// @title Enum - Collection of enums\\n/// @author Richard Meissner - \\ncontract Enum {\\n enum Operation {Call, DelegateCall}\\n}\\n\",\"keccak256\":\"0x473e45b1a5cc47be494b0e123c9127f0c11c1e0992a321ae5a644c0bfdb2c14f\",\"license\":\"LGPL-3.0-only\"},\"@gnosis.pm/zodiac/contracts/interfaces/IAvatar.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\n\\n/// @title Zodiac Avatar - A contract that manages modules that can execute transactions via this contract.\\npragma solidity >=0.7.0 <0.9.0;\\n\\nimport \\\"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\\\";\\n\\ninterface IAvatar {\\n event EnabledModule(address module);\\n event DisabledModule(address module);\\n event ExecutionFromModuleSuccess(address indexed module);\\n event ExecutionFromModuleFailure(address indexed module);\\n\\n /// @dev Enables a module on the avatar.\\n /// @notice Can only be called by the avatar.\\n /// @notice Modules should be stored as a linked list.\\n /// @notice Must emit EnabledModule(address module) if successful.\\n /// @param module Module to be enabled.\\n function enableModule(address module) external;\\n\\n /// @dev Disables a module on the avatar.\\n /// @notice Can only be called by the avatar.\\n /// @notice Must emit DisabledModule(address module) if successful.\\n /// @param prevModule Address that pointed to the module to be removed in the linked list\\n /// @param module Module to be removed.\\n function disableModule(address prevModule, address module) external;\\n\\n /// @dev Allows a Module to execute a transaction.\\n /// @notice Can only be called by an enabled module.\\n /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.\\n /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.\\n /// @param to Destination address of module transaction.\\n /// @param value Ether value of module transaction.\\n /// @param data Data payload of module transaction.\\n /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.\\n function execTransactionFromModule(\\n address to,\\n uint256 value,\\n bytes memory data,\\n Enum.Operation operation\\n ) external returns (bool success);\\n\\n /// @dev Allows a Module to execute a transaction and return data\\n /// @notice Can only be called by an enabled module.\\n /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.\\n /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.\\n /// @param to Destination address of module transaction.\\n /// @param value Ether value of module transaction.\\n /// @param data Data payload of module transaction.\\n /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.\\n function execTransactionFromModuleReturnData(\\n address to,\\n uint256 value,\\n bytes memory data,\\n Enum.Operation operation\\n ) external returns (bool success, bytes memory returnData);\\n\\n /// @dev Returns if an module is enabled\\n /// @return True if the module is enabled\\n function isModuleEnabled(address module) external view returns (bool);\\n\\n /// @dev Returns array of modules.\\n /// @param start Start of the page.\\n /// @param pageSize Maximum number of modules that should be returned.\\n /// @return array Array of modules.\\n /// @return next Start of the next page.\\n function getModulesPaginated(address start, uint256 pageSize)\\n external\\n view\\n returns (address[] memory array, address next);\\n}\\n\",\"keccak256\":\"0xcd5508ffe596eef8fbccfd5fc4f10a34397773547ce64e212d48b5212865ec1f\",\"license\":\"LGPL-3.0-only\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n}\\n\",\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\"},\"contracts/DecentHats_0_1_0.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity =0.8.19;\\n\\nimport {Enum} from \\\"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\\\";\\nimport {IAvatar} from \\\"@gnosis.pm/zodiac/contracts/interfaces/IAvatar.sol\\\";\\nimport {Strings} from \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {IERC6551Registry} from \\\"./interfaces/IERC6551Registry.sol\\\";\\nimport {IHats} from \\\"./interfaces/hats/IHats.sol\\\";\\nimport {ISablierV2LockupLinear} from \\\"./interfaces/sablier/ISablierV2LockupLinear.sol\\\";\\nimport {LockupLinear} from \\\"./interfaces/sablier/LockupLinear.sol\\\";\\n\\ncontract DecentHats_0_1_0 {\\n string public constant NAME = \\\"DecentHats_0_1_0\\\";\\n\\n struct SablierStreamParams {\\n ISablierV2LockupLinear sablier;\\n address sender;\\n uint128 totalAmount;\\n address asset;\\n bool cancelable;\\n bool transferable;\\n LockupLinear.Timestamps timestamps;\\n LockupLinear.Broker broker;\\n }\\n\\n struct Hat {\\n uint32 maxSupply;\\n string details;\\n string imageURI;\\n bool isMutable;\\n address wearer;\\n SablierStreamParams[] sablierParams; // Optional Sablier stream parameters\\n }\\n\\n struct CreateTreeParams {\\n IHats hatsProtocol;\\n address hatsAccountImplementation;\\n IERC6551Registry registry;\\n address keyValuePairs;\\n string topHatDetails;\\n string topHatImageURI;\\n Hat adminHat;\\n Hat[] hats;\\n }\\n\\n function getSalt() internal view returns (bytes32 salt) {\\n uint256 chainId;\\n assembly {\\n chainId := chainid()\\n }\\n\\n bytes memory concatenatedSaltInput = abi.encodePacked(\\n NAME,\\n chainId,\\n address(this)\\n );\\n\\n salt = keccak256(concatenatedSaltInput);\\n }\\n\\n function updateKeyValuePairs(\\n address _keyValuePairs,\\n uint256 topHatId\\n ) internal {\\n string[] memory keys = new string[](1);\\n string[] memory values = new string[](1);\\n keys[0] = \\\"topHatId\\\";\\n values[0] = Strings.toString(topHatId);\\n\\n IAvatar(msg.sender).execTransactionFromModule(\\n _keyValuePairs,\\n 0,\\n abi.encodeWithSignature(\\n \\\"updateValues(string[],string[])\\\",\\n keys,\\n values\\n ),\\n Enum.Operation.Call\\n );\\n }\\n\\n function createHat(\\n IHats _hatsProtocol,\\n uint256 adminHatId,\\n Hat memory _hat,\\n address topHatAccount\\n ) internal returns (uint256) {\\n return\\n _hatsProtocol.createHat(\\n adminHatId,\\n _hat.details,\\n _hat.maxSupply,\\n topHatAccount,\\n topHatAccount,\\n _hat.isMutable,\\n _hat.imageURI\\n );\\n }\\n\\n function createAccount(\\n IERC6551Registry _registry,\\n address _hatsAccountImplementation,\\n bytes32 salt,\\n address protocolAddress,\\n uint256 hatId\\n ) internal returns (address) {\\n return\\n _registry.createAccount(\\n _hatsAccountImplementation,\\n salt,\\n block.chainid,\\n protocolAddress,\\n hatId\\n );\\n }\\n\\n function createTopHatAndAccount(\\n IHats _hatsProtocol,\\n string memory _topHatDetails,\\n string memory _topHatImageURI,\\n IERC6551Registry _registry,\\n address _hatsAccountImplementation,\\n bytes32 salt\\n ) internal returns (uint256 topHatId, address topHatAccount) {\\n topHatId = _hatsProtocol.mintTopHat(\\n address(this),\\n _topHatDetails,\\n _topHatImageURI\\n );\\n\\n topHatAccount = createAccount(\\n _registry,\\n _hatsAccountImplementation,\\n salt,\\n address(_hatsProtocol),\\n topHatId\\n );\\n }\\n\\n function createHatAndAccountAndMintAndStreams(\\n IHats hatsProtocol,\\n uint256 adminHatId,\\n Hat calldata hat,\\n address topHatAccount,\\n IERC6551Registry registry,\\n address hatsAccountImplementation,\\n bytes32 salt\\n ) internal returns (uint256 hatId, address accountAddress) {\\n hatId = createHat(hatsProtocol, adminHatId, hat, topHatAccount);\\n\\n accountAddress = createAccount(\\n registry,\\n hatsAccountImplementation,\\n salt,\\n address(hatsProtocol),\\n hatId\\n );\\n\\n if (hat.wearer != address(0)) {\\n hatsProtocol.mintHat(hatId, hat.wearer);\\n }\\n\\n for (uint256 i = 0; i < hat.sablierParams.length; ) {\\n SablierStreamParams memory sablierParams = hat.sablierParams[i];\\n\\n // Approve tokens for Sablier\\n IAvatar(msg.sender).execTransactionFromModule(\\n sablierParams.asset,\\n 0,\\n abi.encodeWithSignature(\\n \\\"approve(address,uint256)\\\",\\n address(sablierParams.sablier),\\n sablierParams.totalAmount\\n ),\\n Enum.Operation.Call\\n );\\n\\n LockupLinear.CreateWithTimestamps memory params = LockupLinear\\n .CreateWithTimestamps({\\n sender: sablierParams.sender,\\n recipient: accountAddress,\\n totalAmount: sablierParams.totalAmount,\\n asset: IERC20(sablierParams.asset),\\n cancelable: sablierParams.cancelable,\\n transferable: sablierParams.transferable,\\n timestamps: sablierParams.timestamps,\\n broker: sablierParams.broker\\n });\\n\\n // Proxy the Sablier call through IAvatar\\n IAvatar(msg.sender).execTransactionFromModule(\\n address(sablierParams.sablier),\\n 0,\\n abi.encodeWithSignature(\\n \\\"createWithTimestamps((address,address,uint128,address,bool,bool,(uint40,uint40,uint40),(address,uint256)))\\\",\\n params\\n ),\\n Enum.Operation.Call\\n );\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n function createAndDeclareTree(CreateTreeParams calldata params) public {\\n bytes32 salt = getSalt();\\n\\n (uint256 topHatId, address topHatAccount) = createTopHatAndAccount(\\n params.hatsProtocol,\\n params.topHatDetails,\\n params.topHatImageURI,\\n params.registry,\\n params.hatsAccountImplementation,\\n salt\\n );\\n\\n updateKeyValuePairs(params.keyValuePairs, topHatId);\\n\\n (uint256 adminHatId, ) = createHatAndAccountAndMintAndStreams(\\n params.hatsProtocol,\\n topHatId,\\n params.adminHat,\\n topHatAccount,\\n params.registry,\\n params.hatsAccountImplementation,\\n salt\\n );\\n\\n for (uint256 i = 0; i < params.hats.length; ) {\\n createHatAndAccountAndMintAndStreams(\\n params.hatsProtocol,\\n adminHatId,\\n params.hats[i],\\n topHatAccount,\\n params.registry,\\n params.hatsAccountImplementation,\\n salt\\n );\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n params.hatsProtocol.transferHat(topHatId, address(this), msg.sender);\\n }\\n}\\n\",\"keccak256\":\"0xdc0d2b3c556d675f26152895a17e1fb76c91d1a85b2689cf435fb3666381ac41\",\"license\":\"MIT\"},\"contracts/interfaces/IERC6551Registry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IERC6551Registry {\\n /**\\n * @dev Creates a token bound account for a non-fungible token.\\n *\\n * If account has already been created, returns the account address without calling create2.\\n *\\n * Emits ERC6551AccountCreated event.\\n *\\n * @return account The address of the token bound account\\n */\\n function createAccount(\\n address implementation,\\n bytes32 salt,\\n uint256 chainId,\\n address tokenContract,\\n uint256 tokenId\\n ) external returns (address account);\\n}\\n\",\"keccak256\":\"0x64c52de8a8e68398e61dd8b42dda8e9af8cf6abf93bb85629c322440991ea568\",\"license\":\"MIT\"},\"contracts/interfaces/hats/IHats.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0\\n// Copyright (C) 2023 Haberdasher Labs\\n//\\n// This program is free software: you can redistribute it and/or modify\\n// it under the terms of the GNU Affero General Public License as published by\\n// the Free Software Foundation, either version 3 of the License, or\\n// (at your option) any later version.\\n//\\n// This program is distributed in the hope that it will be useful,\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\\n// GNU Affero General Public License for more details.\\n//\\n// You should have received a copy of the GNU Affero General Public License\\n// along with this program. If not, see .\\n\\npragma solidity >=0.8.13;\\n\\ninterface IHats {\\n function mintTopHat(\\n address _target,\\n string memory _details,\\n string memory _imageURI\\n ) external returns (uint256 topHatId);\\n\\n function createHat(\\n uint256 _admin,\\n string calldata _details,\\n uint32 _maxSupply,\\n address _eligibility,\\n address _toggle,\\n bool _mutable,\\n string calldata _imageURI\\n ) external returns (uint256 newHatId);\\n\\n function mintHat(\\n uint256 _hatId,\\n address _wearer\\n ) external returns (bool success);\\n\\n function transferHat(uint256 _hatId, address _from, address _to) external;\\n}\\n\",\"keccak256\":\"0x8e35022f5c0fcf0059033abec78ec890f0cf3bbac09d6d24051cff9679239511\",\"license\":\"AGPL-3.0\"},\"contracts/interfaces/sablier/ISablierV2LockupLinear.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {LockupLinear} from \\\"./LockupLinear.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface ISablierV2LockupLinear {\\n function createWithTimestamps(\\n LockupLinear.CreateWithTimestamps calldata params\\n ) external returns (uint256 streamId);\\n}\\n\",\"keccak256\":\"0xf4899637eb2e6c76c35e2d201e56e162a50e6bc7b5b9156e00866f0703ad07ca\",\"license\":\"MIT\"},\"contracts/interfaces/sablier/LockupLinear.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LockupLinear {\\n struct CreateWithTimestamps {\\n address sender;\\n address recipient;\\n uint128 totalAmount;\\n IERC20 asset;\\n bool cancelable;\\n bool transferable;\\n Timestamps timestamps;\\n Broker broker;\\n }\\n\\n struct Timestamps {\\n uint40 start;\\n uint40 cliff;\\n uint40 end;\\n }\\n\\n struct Broker {\\n address account;\\n uint256 fee;\\n }\\n}\\n\",\"keccak256\":\"0x497fdb52b5e1a5a7e0711a9f7d5fb036eb668ccb92ea908ee088f56ee08a4ce8\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50611477806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80638c5f591a1461003b578063a3f4df7e14610050575b600080fd5b61004e610049366004610ac2565b610095565b005b61007f6040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b81525081565b60405161008c9190610b54565b60405180910390f35b600061009f6102cd565b905060008061015e6100b46020860186610b7f565b6100c16080870187610b9c565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506101039250505060a0880188610b9c565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610148925050506060890160408a01610b7f565b61015860408a0160208b01610b7f565b88610331565b909250905061017c6101766080860160608701610b7f565b836103c3565b60006101c361018e6020870187610b7f565b8461019c60c0890189610bf9565b856101ad60608b0160408c01610b7f565b6101bd60408c0160208d01610b7f565b8a610543565b50905060005b6101d660e0870187610c19565b9050811015610250576102466101ef6020880188610b7f565b836101fd60e08a018a610c19565b8581811061020d5761020d610c62565b905060200281019061021f9190610bf9565b8661023060608c0160408d01610b7f565b61024060408d0160208e01610b7f565b8b610543565b50506001016101c9565b5061025e6020860186610b7f565b6040516329287c1b60e21b8152600481018590523060248201523360448201526001600160a01b03919091169063a4a1f06c90606401600060405180830381600087803b1580156102ae57600080fd5b505af11580156102c2573d6000803e3d6000fd5b505050505050505050565b60008046905060006040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b815250823060405160200161031293929190610c78565b60408051601f1981840301815291905280516020909101209392505050565b600080876001600160a01b0316631a64dfad3089896040518463ffffffff1660e01b815260040161036493929190610cb1565b6020604051808303816000875af1158015610383573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a79190610ce7565b91506103b68585858b86610892565b9050965096945050505050565b604080516001808252818301909252600091816020015b60608152602001906001900390816103da57505060408051600180825281830190925291925060009190602082015b6060815260200190600190039081610409579050509050604051806040016040528060088152602001671d1bdc12185d125960c21b8152508260008151811061045457610454610c62565b602002602001018190525061046883610928565b8160008151811061047b5761047b610c62565b6020026020010181905250336001600160a01b031663468721a785600085856040516024016104ab929190610d6b565b60408051601f198184030181529181526020820180516001600160e01b031663579374b960e11b1790525160e085901b6001600160e01b03191681526104f993929190600090600401610d90565b6020604051808303816000875af1158015610518573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053c9190610df4565b5050505050565b60008061055a89896105548a61113b565b89610a30565b91506105698585858c86610892565b9050600061057d60a0890160808a01610b7f565b6001600160a01b03161461061d576001600160a01b03891663641f776e836105ab60a08b0160808c01610b7f565b6040516001600160e01b031960e085901b16815260048101929092526001600160a01b031660248201526044016020604051808303816000875af11580156105f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061b9190610df4565b505b60005b61062d60a08901896111ff565b905081101561088557600061064560a08a018a6111ff565b8381811061065557610655610c62565b9050610160020180360381019061066c9190611248565b6060810151815160408084015190516001600160a01b0390921660248301526001600160801b03166044820152919250339163468721a7919060009060640160408051601f198184030181529181526020820180516001600160e01b031663095ea7b360e01b1790525160e085901b6001600160e01b03191681526106f993929190600090600401610d90565b6020604051808303816000875af1158015610718573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073c9190610df4565b50600060405180610100016040528083602001516001600160a01b03168152602001856001600160a01b0316815260200183604001516001600160801b0316815260200183606001516001600160a01b031681526020018360800151151581526020018360a00151151581526020018360c0015181526020018360e001518152509050336001600160a01b031663468721a783600001516000846040516024016107e69190611265565b60408051601f198184030181529181526020820180516001600160e01b03166353b1572760e01b1790525160e085901b6001600160e01b031916815261083493929190600090600401610d90565b6020604051808303816000875af1158015610853573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108779190610df4565b508260010192505050610620565b5097509795505050505050565b604051638a54c52f60e01b81526001600160a01b0385811660048301526024820185905246604483015283811660648301526084820183905260009190871690638a54c52f9060a4016020604051808303816000875af11580156108fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091e9190611327565b9695505050505050565b60608160000361094f5750506040805180820190915260018152600360fc1b602082015290565b8160005b811561097957806109638161135a565b91506109729050600a83611389565b9150610953565b6000816001600160401b0381111561099357610993610d00565b6040519080825280601f01601f1916602001820160405280156109bd576020820181803683370190505b5090505b8415610a28576109d260018361139d565b91506109df600a866113b6565b6109ea9060306113ca565b60f81b8183815181106109ff576109ff610c62565b60200101906001600160f81b031916908160001a905350610a21600a86611389565b94506109c1565b949350505050565b6020820151825160608401516040808601519051635829492f60e11b81526000946001600160a01b038a169463b052925e94610a76948b948a92839290916004016113dd565b6020604051808303816000875af1158015610a95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab99190610ce7565b95945050505050565b600060208284031215610ad457600080fd5b81356001600160401b03811115610aea57600080fd5b82016101008185031215610afd57600080fd5b9392505050565b60005b83811015610b1f578181015183820152602001610b07565b50506000910152565b60008151808452610b40816020860160208601610b04565b601f01601f19169290920160200192915050565b602081526000610afd6020830184610b28565b6001600160a01b0381168114610b7c57600080fd5b50565b600060208284031215610b9157600080fd5b8135610afd81610b67565b6000808335601e19843603018112610bb357600080fd5b8301803591506001600160401b03821115610bcd57600080fd5b602001915036819003821315610be257600080fd5b9250929050565b8035610bf481610b67565b919050565b6000823560be19833603018112610c0f57600080fd5b9190910192915050565b6000808335601e19843603018112610c3057600080fd5b8301803591506001600160401b03821115610c4a57600080fd5b6020019150600581901b3603821315610be257600080fd5b634e487b7160e01b600052603260045260246000fd5b60008451610c8a818460208901610b04565b919091019283525060601b6bffffffffffffffffffffffff19166020820152603401919050565b6001600160a01b0384168152606060208201819052600090610cd590830185610b28565b828103604084015261091e8185610b28565b600060208284031215610cf957600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b600081518084526020808501808196508360051b8101915082860160005b85811015610d5e578284038952610d4c848351610b28565b98850198935090840190600101610d34565b5091979650505050505050565b604081526000610d7e6040830185610d16565b8281036020840152610ab98185610d16565b60018060a01b0385168152836020820152608060408201526000610db76080830185610b28565b905060028310610dd757634e487b7160e01b600052602160045260246000fd5b82606083015295945050505050565b8015158114610b7c57600080fd5b600060208284031215610e0657600080fd5b8151610afd81610de6565b60405160c081016001600160401b0381118282101715610e3357610e33610d00565b60405290565b604051601f8201601f191681016001600160401b0381118282101715610e6157610e61610d00565b604052919050565b803563ffffffff81168114610bf457600080fd5b600082601f830112610e8e57600080fd5b81356001600160401b03811115610ea757610ea7610d00565b610eba601f8201601f1916602001610e39565b818152846020838601011115610ecf57600080fd5b816020850160208301376000918101602001919091529392505050565b8035610bf481610de6565b80356001600160801b0381168114610bf457600080fd5b803564ffffffffff81168114610bf457600080fd5b600060608284031215610f3557600080fd5b604051606081018181106001600160401b0382111715610f5757610f57610d00565b604052905080610f6683610f0e565b8152610f7460208401610f0e565b6020820152610f8560408401610f0e565b60408201525092915050565b600060408284031215610fa357600080fd5b604051604081018181106001600160401b0382111715610fc557610fc5610d00565b6040529050808235610fd681610b67565b8152602092830135920191909152919050565b60006101608284031215610ffc57600080fd5b60405161010081018181106001600160401b038211171561101f5761101f610d00565b60405290508061102e83610be9565b815261103c60208401610be9565b602082015261104d60408401610ef7565b604082015261105e60608401610be9565b606082015261106f60808401610eec565b608082015261108060a08401610eec565b60a08201526110928460c08501610f23565b60c08201526110a5846101208501610f91565b60e08201525092915050565b600082601f8301126110c257600080fd5b813560206001600160401b038211156110dd576110dd610d00565b6110eb818360051b01610e39565b828152610160928302850182019282820191908785111561110b57600080fd5b8387015b8581101561112e576111218982610fe9565b845292840192810161110f565b5090979650505050505050565b600060c0823603121561114d57600080fd5b611155610e11565b61115e83610e69565b815260208301356001600160401b038082111561117a57600080fd5b61118636838701610e7d565b6020840152604085013591508082111561119f57600080fd5b6111ab36838701610e7d565b60408401526111bc60608601610eec565b60608401526111cd60808601610be9565b608084015260a08501359150808211156111e657600080fd5b506111f3368286016110b1565b60a08301525092915050565b6000808335601e1984360301811261121657600080fd5b8301803591506001600160401b0382111561123057600080fd5b602001915061016081023603821315610be257600080fd5b6000610160828403121561125b57600080fd5b610afd8383610fe9565b81516001600160a01b0390811682526020808401518216908301526040808401516001600160801b031690830152606080840151909116908201526080808301516101608301916112b99084018215159052565b5060a08301516112cd60a084018215159052565b5060c083015161130060c0840182805164ffffffffff908116835260208083015182169084015260409182015116910152565b5060e0929092015180516001600160a01b0316610120830152602001516101409091015290565b60006020828403121561133957600080fd5b8151610afd81610b67565b634e487b7160e01b600052601160045260246000fd5b60006001820161136c5761136c611344565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261139857611398611373565b500490565b818103818111156113b0576113b0611344565b92915050565b6000826113c5576113c5611373565b500690565b808201808211156113b0576113b0611344565b87815260e0602082015260006113f660e0830189610b28565b63ffffffff881660408401526001600160a01b0387811660608501528616608084015284151560a084015282810360c08401526114338185610b28565b9a995050505050505050505056fea2646970667358221220d17954ba81bca52da6ca1f1cf74a0e04f2ce3c50651d1d806611eb18ab0d551e64736f6c63430008130033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80638c5f591a1461003b578063a3f4df7e14610050575b600080fd5b61004e610049366004610ac2565b610095565b005b61007f6040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b81525081565b60405161008c9190610b54565b60405180910390f35b600061009f6102cd565b905060008061015e6100b46020860186610b7f565b6100c16080870187610b9c565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506101039250505060a0880188610b9c565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610148925050506060890160408a01610b7f565b61015860408a0160208b01610b7f565b88610331565b909250905061017c6101766080860160608701610b7f565b836103c3565b60006101c361018e6020870187610b7f565b8461019c60c0890189610bf9565b856101ad60608b0160408c01610b7f565b6101bd60408c0160208d01610b7f565b8a610543565b50905060005b6101d660e0870187610c19565b9050811015610250576102466101ef6020880188610b7f565b836101fd60e08a018a610c19565b8581811061020d5761020d610c62565b905060200281019061021f9190610bf9565b8661023060608c0160408d01610b7f565b61024060408d0160208e01610b7f565b8b610543565b50506001016101c9565b5061025e6020860186610b7f565b6040516329287c1b60e21b8152600481018590523060248201523360448201526001600160a01b03919091169063a4a1f06c90606401600060405180830381600087803b1580156102ae57600080fd5b505af11580156102c2573d6000803e3d6000fd5b505050505050505050565b60008046905060006040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b815250823060405160200161031293929190610c78565b60408051601f1981840301815291905280516020909101209392505050565b600080876001600160a01b0316631a64dfad3089896040518463ffffffff1660e01b815260040161036493929190610cb1565b6020604051808303816000875af1158015610383573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a79190610ce7565b91506103b68585858b86610892565b9050965096945050505050565b604080516001808252818301909252600091816020015b60608152602001906001900390816103da57505060408051600180825281830190925291925060009190602082015b6060815260200190600190039081610409579050509050604051806040016040528060088152602001671d1bdc12185d125960c21b8152508260008151811061045457610454610c62565b602002602001018190525061046883610928565b8160008151811061047b5761047b610c62565b6020026020010181905250336001600160a01b031663468721a785600085856040516024016104ab929190610d6b565b60408051601f198184030181529181526020820180516001600160e01b031663579374b960e11b1790525160e085901b6001600160e01b03191681526104f993929190600090600401610d90565b6020604051808303816000875af1158015610518573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053c9190610df4565b5050505050565b60008061055a89896105548a61113b565b89610a30565b91506105698585858c86610892565b9050600061057d60a0890160808a01610b7f565b6001600160a01b03161461061d576001600160a01b03891663641f776e836105ab60a08b0160808c01610b7f565b6040516001600160e01b031960e085901b16815260048101929092526001600160a01b031660248201526044016020604051808303816000875af11580156105f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061b9190610df4565b505b60005b61062d60a08901896111ff565b905081101561088557600061064560a08a018a6111ff565b8381811061065557610655610c62565b9050610160020180360381019061066c9190611248565b6060810151815160408084015190516001600160a01b0390921660248301526001600160801b03166044820152919250339163468721a7919060009060640160408051601f198184030181529181526020820180516001600160e01b031663095ea7b360e01b1790525160e085901b6001600160e01b03191681526106f993929190600090600401610d90565b6020604051808303816000875af1158015610718573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073c9190610df4565b50600060405180610100016040528083602001516001600160a01b03168152602001856001600160a01b0316815260200183604001516001600160801b0316815260200183606001516001600160a01b031681526020018360800151151581526020018360a00151151581526020018360c0015181526020018360e001518152509050336001600160a01b031663468721a783600001516000846040516024016107e69190611265565b60408051601f198184030181529181526020820180516001600160e01b03166353b1572760e01b1790525160e085901b6001600160e01b031916815261083493929190600090600401610d90565b6020604051808303816000875af1158015610853573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108779190610df4565b508260010192505050610620565b5097509795505050505050565b604051638a54c52f60e01b81526001600160a01b0385811660048301526024820185905246604483015283811660648301526084820183905260009190871690638a54c52f9060a4016020604051808303816000875af11580156108fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091e9190611327565b9695505050505050565b60608160000361094f5750506040805180820190915260018152600360fc1b602082015290565b8160005b811561097957806109638161135a565b91506109729050600a83611389565b9150610953565b6000816001600160401b0381111561099357610993610d00565b6040519080825280601f01601f1916602001820160405280156109bd576020820181803683370190505b5090505b8415610a28576109d260018361139d565b91506109df600a866113b6565b6109ea9060306113ca565b60f81b8183815181106109ff576109ff610c62565b60200101906001600160f81b031916908160001a905350610a21600a86611389565b94506109c1565b949350505050565b6020820151825160608401516040808601519051635829492f60e11b81526000946001600160a01b038a169463b052925e94610a76948b948a92839290916004016113dd565b6020604051808303816000875af1158015610a95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab99190610ce7565b95945050505050565b600060208284031215610ad457600080fd5b81356001600160401b03811115610aea57600080fd5b82016101008185031215610afd57600080fd5b9392505050565b60005b83811015610b1f578181015183820152602001610b07565b50506000910152565b60008151808452610b40816020860160208601610b04565b601f01601f19169290920160200192915050565b602081526000610afd6020830184610b28565b6001600160a01b0381168114610b7c57600080fd5b50565b600060208284031215610b9157600080fd5b8135610afd81610b67565b6000808335601e19843603018112610bb357600080fd5b8301803591506001600160401b03821115610bcd57600080fd5b602001915036819003821315610be257600080fd5b9250929050565b8035610bf481610b67565b919050565b6000823560be19833603018112610c0f57600080fd5b9190910192915050565b6000808335601e19843603018112610c3057600080fd5b8301803591506001600160401b03821115610c4a57600080fd5b6020019150600581901b3603821315610be257600080fd5b634e487b7160e01b600052603260045260246000fd5b60008451610c8a818460208901610b04565b919091019283525060601b6bffffffffffffffffffffffff19166020820152603401919050565b6001600160a01b0384168152606060208201819052600090610cd590830185610b28565b828103604084015261091e8185610b28565b600060208284031215610cf957600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b600081518084526020808501808196508360051b8101915082860160005b85811015610d5e578284038952610d4c848351610b28565b98850198935090840190600101610d34565b5091979650505050505050565b604081526000610d7e6040830185610d16565b8281036020840152610ab98185610d16565b60018060a01b0385168152836020820152608060408201526000610db76080830185610b28565b905060028310610dd757634e487b7160e01b600052602160045260246000fd5b82606083015295945050505050565b8015158114610b7c57600080fd5b600060208284031215610e0657600080fd5b8151610afd81610de6565b60405160c081016001600160401b0381118282101715610e3357610e33610d00565b60405290565b604051601f8201601f191681016001600160401b0381118282101715610e6157610e61610d00565b604052919050565b803563ffffffff81168114610bf457600080fd5b600082601f830112610e8e57600080fd5b81356001600160401b03811115610ea757610ea7610d00565b610eba601f8201601f1916602001610e39565b818152846020838601011115610ecf57600080fd5b816020850160208301376000918101602001919091529392505050565b8035610bf481610de6565b80356001600160801b0381168114610bf457600080fd5b803564ffffffffff81168114610bf457600080fd5b600060608284031215610f3557600080fd5b604051606081018181106001600160401b0382111715610f5757610f57610d00565b604052905080610f6683610f0e565b8152610f7460208401610f0e565b6020820152610f8560408401610f0e565b60408201525092915050565b600060408284031215610fa357600080fd5b604051604081018181106001600160401b0382111715610fc557610fc5610d00565b6040529050808235610fd681610b67565b8152602092830135920191909152919050565b60006101608284031215610ffc57600080fd5b60405161010081018181106001600160401b038211171561101f5761101f610d00565b60405290508061102e83610be9565b815261103c60208401610be9565b602082015261104d60408401610ef7565b604082015261105e60608401610be9565b606082015261106f60808401610eec565b608082015261108060a08401610eec565b60a08201526110928460c08501610f23565b60c08201526110a5846101208501610f91565b60e08201525092915050565b600082601f8301126110c257600080fd5b813560206001600160401b038211156110dd576110dd610d00565b6110eb818360051b01610e39565b828152610160928302850182019282820191908785111561110b57600080fd5b8387015b8581101561112e576111218982610fe9565b845292840192810161110f565b5090979650505050505050565b600060c0823603121561114d57600080fd5b611155610e11565b61115e83610e69565b815260208301356001600160401b038082111561117a57600080fd5b61118636838701610e7d565b6020840152604085013591508082111561119f57600080fd5b6111ab36838701610e7d565b60408401526111bc60608601610eec565b60608401526111cd60808601610be9565b608084015260a08501359150808211156111e657600080fd5b506111f3368286016110b1565b60a08301525092915050565b6000808335601e1984360301811261121657600080fd5b8301803591506001600160401b0382111561123057600080fd5b602001915061016081023603821315610be257600080fd5b6000610160828403121561125b57600080fd5b610afd8383610fe9565b81516001600160a01b0390811682526020808401518216908301526040808401516001600160801b031690830152606080840151909116908201526080808301516101608301916112b99084018215159052565b5060a08301516112cd60a084018215159052565b5060c083015161130060c0840182805164ffffffffff908116835260208083015182169084015260409182015116910152565b5060e0929092015180516001600160a01b0316610120830152602001516101409091015290565b60006020828403121561133957600080fd5b8151610afd81610b67565b634e487b7160e01b600052601160045260246000fd5b60006001820161136c5761136c611344565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261139857611398611373565b500490565b818103818111156113b0576113b0611344565b92915050565b6000826113c5576113c5611373565b500690565b808201808211156113b0576113b0611344565b87815260e0602082015260006113f660e0830189610b28565b63ffffffff881660408401526001600160a01b0387811660608501528616608084015284151560a084015282810360c08401526114338185610b28565b9a995050505050505050505056fea2646970667358221220d17954ba81bca52da6ca1f1cf74a0e04f2ce3c50651d1d806611eb18ab0d551e64736f6c63430008130033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/optimism/solcInputs/512807b5d71481c693c202ae23158904.json b/deployments/optimism/solcInputs/512807b5d71481c693c202ae23158904.json new file mode 100644 index 00000000..0d0d55c8 --- /dev/null +++ b/deployments/optimism/solcInputs/512807b5d71481c693c202ae23158904.json @@ -0,0 +1,59 @@ +{ + "language": "Solidity", + "sources": { + "@gnosis.pm/safe-contracts/contracts/common/Enum.sol": { + "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.0 <0.9.0;\n\n/// @title Enum - Collection of enums\n/// @author Richard Meissner - \ncontract Enum {\n enum Operation {Call, DelegateCall}\n}\n" + }, + "@gnosis.pm/zodiac/contracts/interfaces/IAvatar.sol": { + "content": "// SPDX-License-Identifier: LGPL-3.0-only\n\n/// @title Zodiac Avatar - A contract that manages modules that can execute transactions via this contract.\npragma solidity >=0.7.0 <0.9.0;\n\nimport \"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\";\n\ninterface IAvatar {\n event EnabledModule(address module);\n event DisabledModule(address module);\n event ExecutionFromModuleSuccess(address indexed module);\n event ExecutionFromModuleFailure(address indexed module);\n\n /// @dev Enables a module on the avatar.\n /// @notice Can only be called by the avatar.\n /// @notice Modules should be stored as a linked list.\n /// @notice Must emit EnabledModule(address module) if successful.\n /// @param module Module to be enabled.\n function enableModule(address module) external;\n\n /// @dev Disables a module on the avatar.\n /// @notice Can only be called by the avatar.\n /// @notice Must emit DisabledModule(address module) if successful.\n /// @param prevModule Address that pointed to the module to be removed in the linked list\n /// @param module Module to be removed.\n function disableModule(address prevModule, address module) external;\n\n /// @dev Allows a Module to execute a transaction.\n /// @notice Can only be called by an enabled module.\n /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.\n /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.\n /// @param to Destination address of module transaction.\n /// @param value Ether value of module transaction.\n /// @param data Data payload of module transaction.\n /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.\n function execTransactionFromModule(\n address to,\n uint256 value,\n bytes memory data,\n Enum.Operation operation\n ) external returns (bool success);\n\n /// @dev Allows a Module to execute a transaction and return data\n /// @notice Can only be called by an enabled module.\n /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.\n /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.\n /// @param to Destination address of module transaction.\n /// @param value Ether value of module transaction.\n /// @param data Data payload of module transaction.\n /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.\n function execTransactionFromModuleReturnData(\n address to,\n uint256 value,\n bytes memory data,\n Enum.Operation operation\n ) external returns (bool success, bytes memory returnData);\n\n /// @dev Returns if an module is enabled\n /// @return True if the module is enabled\n function isModuleEnabled(address module) external view returns (bool);\n\n /// @dev Returns array of modules.\n /// @param start Start of the page.\n /// @param pageSize Maximum number of modules that should be returned.\n /// @return array Array of modules.\n /// @return next Start of the next page.\n function getModulesPaginated(address start, uint256 pageSize)\n external\n view\n returns (address[] memory array, address next);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp >>= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n" + }, + "contracts/DecentHats_0_1_0.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity =0.8.19;\n\nimport {Enum} from \"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\";\nimport {IAvatar} from \"@gnosis.pm/zodiac/contracts/interfaces/IAvatar.sol\";\nimport {Strings} from \"@openzeppelin/contracts/utils/Strings.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {IERC6551Registry} from \"./interfaces/IERC6551Registry.sol\";\nimport {IHats} from \"./interfaces/hats/IHats.sol\";\nimport {ISablierV2LockupLinear} from \"./interfaces/sablier/ISablierV2LockupLinear.sol\";\nimport {LockupLinear} from \"./interfaces/sablier/LockupLinear.sol\";\n\ncontract DecentHats_0_1_0 {\n string public constant NAME = \"DecentHats_0_1_0\";\n\n struct SablierStreamParams {\n ISablierV2LockupLinear sablier;\n address sender;\n uint128 totalAmount;\n address asset;\n bool cancelable;\n bool transferable;\n LockupLinear.Timestamps timestamps;\n LockupLinear.Broker broker;\n }\n\n struct Hat {\n uint32 maxSupply;\n string details;\n string imageURI;\n bool isMutable;\n address wearer;\n SablierStreamParams[] sablierParams; // Optional Sablier stream parameters\n }\n\n struct CreateTreeParams {\n IHats hatsProtocol;\n address hatsAccountImplementation;\n IERC6551Registry registry;\n address keyValuePairs;\n string topHatDetails;\n string topHatImageURI;\n Hat adminHat;\n Hat[] hats;\n }\n\n function getSalt() internal view returns (bytes32 salt) {\n uint256 chainId;\n assembly {\n chainId := chainid()\n }\n\n bytes memory concatenatedSaltInput = abi.encodePacked(\n NAME,\n chainId,\n address(this)\n );\n\n salt = keccak256(concatenatedSaltInput);\n }\n\n function updateKeyValuePairs(\n address _keyValuePairs,\n uint256 topHatId\n ) internal {\n string[] memory keys = new string[](1);\n string[] memory values = new string[](1);\n keys[0] = \"topHatId\";\n values[0] = Strings.toString(topHatId);\n\n IAvatar(msg.sender).execTransactionFromModule(\n _keyValuePairs,\n 0,\n abi.encodeWithSignature(\n \"updateValues(string[],string[])\",\n keys,\n values\n ),\n Enum.Operation.Call\n );\n }\n\n function createHat(\n IHats _hatsProtocol,\n uint256 adminHatId,\n Hat memory _hat,\n address topHatAccount\n ) internal returns (uint256) {\n return\n _hatsProtocol.createHat(\n adminHatId,\n _hat.details,\n _hat.maxSupply,\n topHatAccount,\n topHatAccount,\n _hat.isMutable,\n _hat.imageURI\n );\n }\n\n function createAccount(\n IERC6551Registry _registry,\n address _hatsAccountImplementation,\n bytes32 salt,\n address protocolAddress,\n uint256 hatId\n ) internal returns (address) {\n return\n _registry.createAccount(\n _hatsAccountImplementation,\n salt,\n block.chainid,\n protocolAddress,\n hatId\n );\n }\n\n function createTopHatAndAccount(\n IHats _hatsProtocol,\n string memory _topHatDetails,\n string memory _topHatImageURI,\n IERC6551Registry _registry,\n address _hatsAccountImplementation,\n bytes32 salt\n ) internal returns (uint256 topHatId, address topHatAccount) {\n topHatId = _hatsProtocol.mintTopHat(\n address(this),\n _topHatDetails,\n _topHatImageURI\n );\n\n topHatAccount = createAccount(\n _registry,\n _hatsAccountImplementation,\n salt,\n address(_hatsProtocol),\n topHatId\n );\n }\n\n function createHatAndAccountAndMintAndStreams(\n IHats hatsProtocol,\n uint256 adminHatId,\n Hat calldata hat,\n address topHatAccount,\n IERC6551Registry registry,\n address hatsAccountImplementation,\n bytes32 salt\n ) internal returns (uint256 hatId, address accountAddress) {\n hatId = createHat(hatsProtocol, adminHatId, hat, topHatAccount);\n\n accountAddress = createAccount(\n registry,\n hatsAccountImplementation,\n salt,\n address(hatsProtocol),\n hatId\n );\n\n if (hat.wearer != address(0)) {\n hatsProtocol.mintHat(hatId, hat.wearer);\n }\n\n for (uint256 i = 0; i < hat.sablierParams.length; ) {\n SablierStreamParams memory sablierParams = hat.sablierParams[i];\n\n // Approve tokens for Sablier\n IAvatar(msg.sender).execTransactionFromModule(\n sablierParams.asset,\n 0,\n abi.encodeWithSignature(\n \"approve(address,uint256)\",\n address(sablierParams.sablier),\n sablierParams.totalAmount\n ),\n Enum.Operation.Call\n );\n\n LockupLinear.CreateWithTimestamps memory params = LockupLinear\n .CreateWithTimestamps({\n sender: sablierParams.sender,\n recipient: accountAddress,\n totalAmount: sablierParams.totalAmount,\n asset: IERC20(sablierParams.asset),\n cancelable: sablierParams.cancelable,\n transferable: sablierParams.transferable,\n timestamps: sablierParams.timestamps,\n broker: sablierParams.broker\n });\n\n // Proxy the Sablier call through IAvatar\n IAvatar(msg.sender).execTransactionFromModule(\n address(sablierParams.sablier),\n 0,\n abi.encodeWithSignature(\n \"createWithTimestamps((address,address,uint128,address,bool,bool,(uint40,uint40,uint40),(address,uint256)))\",\n params\n ),\n Enum.Operation.Call\n );\n\n unchecked {\n ++i;\n }\n }\n }\n\n function createAndDeclareTree(CreateTreeParams calldata params) public {\n bytes32 salt = getSalt();\n\n (uint256 topHatId, address topHatAccount) = createTopHatAndAccount(\n params.hatsProtocol,\n params.topHatDetails,\n params.topHatImageURI,\n params.registry,\n params.hatsAccountImplementation,\n salt\n );\n\n updateKeyValuePairs(params.keyValuePairs, topHatId);\n\n (uint256 adminHatId, ) = createHatAndAccountAndMintAndStreams(\n params.hatsProtocol,\n topHatId,\n params.adminHat,\n topHatAccount,\n params.registry,\n params.hatsAccountImplementation,\n salt\n );\n\n for (uint256 i = 0; i < params.hats.length; ) {\n createHatAndAccountAndMintAndStreams(\n params.hatsProtocol,\n adminHatId,\n params.hats[i],\n topHatAccount,\n params.registry,\n params.hatsAccountImplementation,\n salt\n );\n\n unchecked {\n ++i;\n }\n }\n\n params.hatsProtocol.transferHat(topHatId, address(this), msg.sender);\n }\n}\n" + }, + "contracts/interfaces/hats/IHats.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0\n// Copyright (C) 2023 Haberdasher Labs\n//\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU Affero General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU Affero General Public License for more details.\n//\n// You should have received a copy of the GNU Affero General Public License\n// along with this program. If not, see .\n\npragma solidity >=0.8.13;\n\ninterface IHats {\n function mintTopHat(\n address _target,\n string memory _details,\n string memory _imageURI\n ) external returns (uint256 topHatId);\n\n function createHat(\n uint256 _admin,\n string calldata _details,\n uint32 _maxSupply,\n address _eligibility,\n address _toggle,\n bool _mutable,\n string calldata _imageURI\n ) external returns (uint256 newHatId);\n\n function mintHat(\n uint256 _hatId,\n address _wearer\n ) external returns (bool success);\n\n function transferHat(uint256 _hatId, address _from, address _to) external;\n}\n" + }, + "contracts/interfaces/IERC6551Registry.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\ninterface IERC6551Registry {\n /**\n * @dev Creates a token bound account for a non-fungible token.\n *\n * If account has already been created, returns the account address without calling create2.\n *\n * Emits ERC6551AccountCreated event.\n *\n * @return account The address of the token bound account\n */\n function createAccount(\n address implementation,\n bytes32 salt,\n uint256 chainId,\n address tokenContract,\n uint256 tokenId\n ) external returns (address account);\n}\n" + }, + "contracts/interfaces/sablier/ISablierV2LockupLinear.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {LockupLinear} from \"./LockupLinear.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface ISablierV2LockupLinear {\n function createWithTimestamps(\n LockupLinear.CreateWithTimestamps calldata params\n ) external returns (uint256 streamId);\n}\n" + }, + "contracts/interfaces/sablier/LockupLinear.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LockupLinear {\n struct CreateWithTimestamps {\n address sender;\n address recipient;\n uint128 totalAmount;\n IERC20 asset;\n bool cancelable;\n bool transferable;\n Timestamps timestamps;\n Broker broker;\n }\n\n struct Timestamps {\n uint40 start;\n uint40 cliff;\n uint40 end;\n }\n\n struct Broker {\n address account;\n uint256 fee;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/deployments/polygon/DecentHats_0_1_0.json b/deployments/polygon/DecentHats_0_1_0.json index c78a156c..c61a33d3 100644 --- a/deployments/polygon/DecentHats_0_1_0.json +++ b/deployments/polygon/DecentHats_0_1_0.json @@ -1,5 +1,5 @@ { - "address": "0xB1011541a6c195540506A0272E4Bb2f53797b477", + "address": "0xFe376AAD5bB1c3Ce27fb27Ece130F7B0ba8D9642", "abi": [ { "inputs": [], @@ -74,6 +74,82 @@ "internalType": "address", "name": "wearer", "type": "address" + }, + { + "components": [ + { + "internalType": "contract ISablierV2LockupLinear", + "name": "sablier", + "type": "address" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint128", + "name": "totalAmount", + "type": "uint128" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "bool", + "name": "cancelable", + "type": "bool" + }, + { + "internalType": "bool", + "name": "transferable", + "type": "bool" + }, + { + "components": [ + { + "internalType": "uint40", + "name": "start", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "cliff", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "end", + "type": "uint40" + } + ], + "internalType": "struct LockupLinear.Timestamps", + "name": "timestamps", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "fee", + "type": "uint256" + } + ], + "internalType": "struct LockupLinear.Broker", + "name": "broker", + "type": "tuple" + } + ], + "internalType": "struct DecentHats_0_1_0.SablierStreamParams[]", + "name": "sablierParams", + "type": "tuple[]" } ], "internalType": "struct DecentHats_0_1_0.Hat", @@ -106,6 +182,82 @@ "internalType": "address", "name": "wearer", "type": "address" + }, + { + "components": [ + { + "internalType": "contract ISablierV2LockupLinear", + "name": "sablier", + "type": "address" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint128", + "name": "totalAmount", + "type": "uint128" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "bool", + "name": "cancelable", + "type": "bool" + }, + { + "internalType": "bool", + "name": "transferable", + "type": "bool" + }, + { + "components": [ + { + "internalType": "uint40", + "name": "start", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "cliff", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "end", + "type": "uint40" + } + ], + "internalType": "struct LockupLinear.Timestamps", + "name": "timestamps", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "fee", + "type": "uint256" + } + ], + "internalType": "struct LockupLinear.Broker", + "name": "broker", + "type": "tuple" + } + ], + "internalType": "struct DecentHats_0_1_0.SablierStreamParams[]", + "name": "sablierParams", + "type": "tuple[]" } ], "internalType": "struct DecentHats_0_1_0.Hat[]", @@ -124,44 +276,44 @@ "type": "function" } ], - "transactionHash": "0x79bae7a0a440de979bf3b83344e2a6190351bd9f0119ba0292832553c61c0123", + "transactionHash": "0x8c847e6203727e72edd6e26fd766f001b00b4f376b8b5d213747c4810b88f0aa", "receipt": { "to": null, "from": "0xb5Ca125166C1987A35EDD550E16846Fa1e1D9bB3", - "contractAddress": "0xB1011541a6c195540506A0272E4Bb2f53797b477", - "transactionIndex": 51, - "gasUsed": "848547", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000008000000000000000800000000000000000000100000000000000000000000000000000000000000000000000000800100080000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000100000000000004000000000000000000001000000000000000000000000000000100004000000000000000000200000000000000000000000000000000000000000000000100000", - "blockHash": "0x3efc6b22989316b71e8440179113903833b0ad12ccbc7f19ad71eb0cfc32d705", - "transactionHash": "0x79bae7a0a440de979bf3b83344e2a6190351bd9f0119ba0292832553c61c0123", + "contractAddress": "0xFe376AAD5bB1c3Ce27fb27Ece130F7B0ba8D9642", + "transactionIndex": 21, + "gasUsed": "1184549", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000008000000000000000000000000000000080000000000000000000000000800000000000000000000100000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000080000200000000000000000000000000000000000000000000000100000000000004000000000000000000001000000000000000000000000000000100004000000000000000000200000000000000000000000000000000000000000000000100000", + "blockHash": "0x45cf379015e0b94be073160f13083eca51f6ae16633be5a9b0061bc8d582fea6", + "transactionHash": "0x8c847e6203727e72edd6e26fd766f001b00b4f376b8b5d213747c4810b88f0aa", "logs": [ { - "transactionIndex": 51, - "blockNumber": 59178497, - "transactionHash": "0x79bae7a0a440de979bf3b83344e2a6190351bd9f0119ba0292832553c61c0123", + "transactionIndex": 21, + "blockNumber": 61707503, + "transactionHash": "0x8c847e6203727e72edd6e26fd766f001b00b4f376b8b5d213747c4810b88f0aa", "address": "0x0000000000000000000000000000000000001010", "topics": [ "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63", "0x0000000000000000000000000000000000000000000000000000000000001010", "0x000000000000000000000000b5ca125166c1987a35edd550e16846fa1e1d9bb3", - "0x00000000000000000000000083d69448f88bf9c701c1b93f43e1f753d39b2632" + "0x000000000000000000000000f0245f6251bef9447a08766b9da2b07b28ad80b0" ], - "data": "0x000000000000000000000000000000000000000000000000005ef617f16d1375000000000000000000000000000000000000000000000000355f6c627e805edb0000000000000000000000000000000000000000000002523c69df5dd90632020000000000000000000000000000000000000000000000003500764a8d134b660000000000000000000000000000000000000000000002523cc8d575ca734577", - "logIndex": 697, - "blockHash": "0x3efc6b22989316b71e8440179113903833b0ad12ccbc7f19ad71eb0cfc32d705" + "data": "0x00000000000000000000000000000000000000000000000000bd6058c704764d0000000000000000000000000000000000000000000000003500764a878ffbff0000000000000000000000000000000000000000000007c594b667ebb781d267000000000000000000000000000000000000000000000000344315f1c08b85b20000000000000000000000000000000000000000000007c59573c8447e8648b4", + "logIndex": 74, + "blockHash": "0x45cf379015e0b94be073160f13083eca51f6ae16633be5a9b0061bc8d582fea6" } ], - "blockNumber": 59178497, - "cumulativeGasUsed": "13715039", + "blockNumber": 61707503, + "cumulativeGasUsed": "3780485", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "88a7dc38a4aa54f89c0bd740dfe90545", - "metadata": "{\"compiler\":{\"version\":\"0.8.19+commit.7dd6d404\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"NAME\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contract IHats\",\"name\":\"hatsProtocol\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"hatsAccountImplementation\",\"type\":\"address\"},{\"internalType\":\"contract IERC6551Registry\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"keyValuePairs\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"topHatDetails\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"topHatImageURI\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxSupply\",\"type\":\"uint32\"},{\"internalType\":\"string\",\"name\":\"details\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"imageURI\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isMutable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"wearer\",\"type\":\"address\"}],\"internalType\":\"struct DecentHats_0_1_0.Hat\",\"name\":\"adminHat\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxSupply\",\"type\":\"uint32\"},{\"internalType\":\"string\",\"name\":\"details\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"imageURI\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isMutable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"wearer\",\"type\":\"address\"}],\"internalType\":\"struct DecentHats_0_1_0.Hat[]\",\"name\":\"hats\",\"type\":\"tuple[]\"}],\"internalType\":\"struct DecentHats_0_1_0.CreateTreeParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"createAndDeclareTree\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/DecentHats_0_1_0.sol\":\"DecentHats_0_1_0\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.7.0 <0.9.0;\\n\\n/// @title Enum - Collection of enums\\n/// @author Richard Meissner - \\ncontract Enum {\\n enum Operation {Call, DelegateCall}\\n}\\n\",\"keccak256\":\"0x473e45b1a5cc47be494b0e123c9127f0c11c1e0992a321ae5a644c0bfdb2c14f\",\"license\":\"LGPL-3.0-only\"},\"@gnosis.pm/zodiac/contracts/interfaces/IAvatar.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\n\\n/// @title Zodiac Avatar - A contract that manages modules that can execute transactions via this contract.\\npragma solidity >=0.7.0 <0.9.0;\\n\\nimport \\\"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\\\";\\n\\ninterface IAvatar {\\n event EnabledModule(address module);\\n event DisabledModule(address module);\\n event ExecutionFromModuleSuccess(address indexed module);\\n event ExecutionFromModuleFailure(address indexed module);\\n\\n /// @dev Enables a module on the avatar.\\n /// @notice Can only be called by the avatar.\\n /// @notice Modules should be stored as a linked list.\\n /// @notice Must emit EnabledModule(address module) if successful.\\n /// @param module Module to be enabled.\\n function enableModule(address module) external;\\n\\n /// @dev Disables a module on the avatar.\\n /// @notice Can only be called by the avatar.\\n /// @notice Must emit DisabledModule(address module) if successful.\\n /// @param prevModule Address that pointed to the module to be removed in the linked list\\n /// @param module Module to be removed.\\n function disableModule(address prevModule, address module) external;\\n\\n /// @dev Allows a Module to execute a transaction.\\n /// @notice Can only be called by an enabled module.\\n /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.\\n /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.\\n /// @param to Destination address of module transaction.\\n /// @param value Ether value of module transaction.\\n /// @param data Data payload of module transaction.\\n /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.\\n function execTransactionFromModule(\\n address to,\\n uint256 value,\\n bytes memory data,\\n Enum.Operation operation\\n ) external returns (bool success);\\n\\n /// @dev Allows a Module to execute a transaction and return data\\n /// @notice Can only be called by an enabled module.\\n /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.\\n /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.\\n /// @param to Destination address of module transaction.\\n /// @param value Ether value of module transaction.\\n /// @param data Data payload of module transaction.\\n /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.\\n function execTransactionFromModuleReturnData(\\n address to,\\n uint256 value,\\n bytes memory data,\\n Enum.Operation operation\\n ) external returns (bool success, bytes memory returnData);\\n\\n /// @dev Returns if an module is enabled\\n /// @return True if the module is enabled\\n function isModuleEnabled(address module) external view returns (bool);\\n\\n /// @dev Returns array of modules.\\n /// @param start Start of the page.\\n /// @param pageSize Maximum number of modules that should be returned.\\n /// @return array Array of modules.\\n /// @return next Start of the next page.\\n function getModulesPaginated(address start, uint256 pageSize)\\n external\\n view\\n returns (address[] memory array, address next);\\n}\\n\",\"keccak256\":\"0xcd5508ffe596eef8fbccfd5fc4f10a34397773547ce64e212d48b5212865ec1f\",\"license\":\"LGPL-3.0-only\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n}\\n\",\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\"},\"contracts/DecentHats_0_1_0.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity =0.8.19;\\n\\nimport {Enum} from \\\"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\\\";\\nimport {IAvatar} from \\\"@gnosis.pm/zodiac/contracts/interfaces/IAvatar.sol\\\";\\nimport {Strings} from \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\nimport {IERC6551Registry} from \\\"./interfaces/IERC6551Registry.sol\\\";\\nimport {IHats} from \\\"./interfaces/hats/IHats.sol\\\";\\n\\ncontract DecentHats_0_1_0 {\\n string public constant NAME = \\\"DecentHats_0_1_0\\\";\\n\\n struct Hat {\\n uint32 maxSupply;\\n string details;\\n string imageURI;\\n bool isMutable;\\n address wearer;\\n }\\n\\n struct CreateTreeParams {\\n IHats hatsProtocol;\\n address hatsAccountImplementation;\\n IERC6551Registry registry;\\n address keyValuePairs;\\n string topHatDetails;\\n string topHatImageURI;\\n Hat adminHat;\\n Hat[] hats;\\n }\\n\\n function getSalt() internal view returns (bytes32 salt) {\\n uint256 chainId;\\n assembly {\\n chainId := chainid()\\n }\\n\\n bytes memory concatenatedSaltInput = abi.encodePacked(\\n NAME,\\n chainId,\\n address(this)\\n );\\n\\n salt = keccak256(concatenatedSaltInput);\\n }\\n\\n function createTopHat(\\n IHats _hatsProtocol,\\n string memory _topHatDetails,\\n string memory _topHatImageURI\\n ) internal returns (uint256) {\\n return\\n _hatsProtocol.mintTopHat(\\n address(this),\\n _topHatDetails,\\n _topHatImageURI\\n );\\n }\\n\\n function createAccount(\\n IERC6551Registry _registry,\\n address _hatsAccountImplementation,\\n bytes32 salt,\\n address protocolAddress,\\n uint256 hatId\\n ) internal returns (address) {\\n return\\n _registry.createAccount(\\n _hatsAccountImplementation,\\n salt,\\n block.chainid,\\n protocolAddress,\\n hatId\\n );\\n }\\n\\n function updateKeyValuePairs(\\n address _keyValuePairs,\\n uint256 topHatId\\n ) internal {\\n string[] memory keys = new string[](1);\\n string[] memory values = new string[](1);\\n keys[0] = \\\"topHatId\\\";\\n values[0] = Strings.toString(topHatId);\\n\\n IAvatar(msg.sender).execTransactionFromModule(\\n _keyValuePairs,\\n 0,\\n abi.encodeWithSignature(\\n \\\"updateValues(string[],string[])\\\",\\n keys,\\n values\\n ),\\n Enum.Operation.Call\\n );\\n }\\n\\n function createHat(\\n IHats _hatsProtocol,\\n uint256 adminHatId,\\n Hat memory _hat,\\n address topHatAccount\\n ) internal returns (uint256) {\\n return\\n _hatsProtocol.createHat(\\n adminHatId,\\n _hat.details,\\n _hat.maxSupply,\\n topHatAccount,\\n topHatAccount,\\n _hat.isMutable,\\n _hat.imageURI\\n );\\n }\\n\\n function createHatAccountMint(\\n IHats hatsProtocol,\\n uint256 adminHatId,\\n Hat calldata hat,\\n address topHatAccount,\\n IERC6551Registry registry,\\n address hatsAccountImplementation,\\n bytes32 salt\\n ) internal returns (uint256 hatId, address accountAddress) {\\n hatId = createHat(hatsProtocol, adminHatId, hat, topHatAccount);\\n\\n accountAddress = createAccount(\\n registry,\\n hatsAccountImplementation,\\n salt,\\n address(hatsProtocol),\\n hatId\\n );\\n\\n if (hat.wearer != address(0)) {\\n hatsProtocol.mintHat(hatId, hat.wearer);\\n }\\n }\\n\\n function handleHats(\\n IHats _hatsProtocol,\\n IERC6551Registry _registry,\\n address _hatsAccountImplementation,\\n bytes32 salt,\\n address topHatAccount,\\n uint256 adminHatId,\\n Hat[] calldata _hats\\n ) internal {\\n for (uint256 i = 0; i < _hats.length; ) {\\n createHatAccountMint(\\n _hatsProtocol,\\n adminHatId,\\n _hats[i],\\n topHatAccount,\\n _registry,\\n _hatsAccountImplementation,\\n salt\\n );\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n function createAndDeclareTree(CreateTreeParams calldata params) public {\\n bytes32 salt = getSalt();\\n uint256 topHatId = createTopHat(\\n params.hatsProtocol,\\n params.topHatDetails,\\n params.topHatImageURI\\n );\\n address topHatAccount = createAccount(\\n params.registry,\\n params.hatsAccountImplementation,\\n salt,\\n address(params.hatsProtocol),\\n topHatId\\n );\\n\\n updateKeyValuePairs(params.keyValuePairs, topHatId);\\n\\n (uint256 adminHatId, ) = createHatAccountMint(\\n params.hatsProtocol,\\n topHatId,\\n params.adminHat,\\n topHatAccount,\\n params.registry,\\n params.hatsAccountImplementation,\\n salt\\n );\\n\\n handleHats(\\n params.hatsProtocol,\\n params.registry,\\n params.hatsAccountImplementation,\\n salt,\\n topHatAccount,\\n adminHatId,\\n params.hats\\n );\\n\\n params.hatsProtocol.transferHat(topHatId, address(this), msg.sender);\\n }\\n}\\n\",\"keccak256\":\"0xd7dbbda48b0f7eedeef3882aab51e93c4881a47bcb09b2f9a20989d22259f027\",\"license\":\"MIT\"},\"contracts/interfaces/IERC6551Registry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IERC6551Registry {\\n /**\\n * @dev Creates a token bound account for a non-fungible token.\\n *\\n * If account has already been created, returns the account address without calling create2.\\n *\\n * Emits ERC6551AccountCreated event.\\n *\\n * @return account The address of the token bound account\\n */\\n function createAccount(\\n address implementation,\\n bytes32 salt,\\n uint256 chainId,\\n address tokenContract,\\n uint256 tokenId\\n ) external returns (address account);\\n}\\n\",\"keccak256\":\"0x64c52de8a8e68398e61dd8b42dda8e9af8cf6abf93bb85629c322440991ea568\",\"license\":\"MIT\"},\"contracts/interfaces/hats/IHats.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0\\n// Copyright (C) 2023 Haberdasher Labs\\n//\\n// This program is free software: you can redistribute it and/or modify\\n// it under the terms of the GNU Affero General Public License as published by\\n// the Free Software Foundation, either version 3 of the License, or\\n// (at your option) any later version.\\n//\\n// This program is distributed in the hope that it will be useful,\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\\n// GNU Affero General Public License for more details.\\n//\\n// You should have received a copy of the GNU Affero General Public License\\n// along with this program. If not, see .\\n\\npragma solidity >=0.8.13;\\n\\ninterface IHats {\\n function mintTopHat(\\n address _target,\\n string memory _details,\\n string memory _imageURI\\n ) external returns (uint256 topHatId);\\n\\n function createHat(\\n uint256 _admin,\\n string calldata _details,\\n uint32 _maxSupply,\\n address _eligibility,\\n address _toggle,\\n bool _mutable,\\n string calldata _imageURI\\n ) external returns (uint256 newHatId);\\n\\n function mintHat(\\n uint256 _hatId,\\n address _wearer\\n ) external returns (bool success);\\n\\n function transferHat(uint256 _hatId, address _from, address _to) external;\\n}\\n\",\"keccak256\":\"0x8e35022f5c0fcf0059033abec78ec890f0cf3bbac09d6d24051cff9679239511\",\"license\":\"AGPL-3.0\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50610e63806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063a3f4df7e1461003b578063c1bce50714610080575b600080fd5b61006a6040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b81525081565b60405161007791906108a5565b60405180910390f35b61009361008e3660046108bf565b610095565b005b600061009f61029d565b9050600061013c6100b36020850185610913565b6100c06080860186610930565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506101029250505060a0870187610930565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061030192505050565b905060006101776101536060860160408701610913565b6101636040870160208801610913565b856101716020890189610913565b8661037f565b905061019261018c6080860160608701610913565b83610415565b60006101d96101a46020870187610913565b846101b260c089018961098e565b856101c360608b0160408c01610913565b6101d360408c0160208d01610913565b8a610595565b5090506102216101ec6020870187610913565b6101fc6060880160408901610913565b61020c6040890160208a01610913565b87868661021c60e08d018d6109ae565b61067b565b61022e6020860186610913565b6040516329287c1b60e21b8152600481018590523060248201523360448201526001600160a01b03919091169063a4a1f06c90606401600060405180830381600087803b15801561027e57600080fd5b505af1158015610292573d6000803e3d6000fd5b505050505050505050565b60008046905060006040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b81525082306040516020016102e2939291906109f8565b60408051601f1981840301815291905280516020909101209392505050565b604051631a64dfad60e01b81526000906001600160a01b03851690631a64dfad9061033490309087908790600401610a31565b6020604051808303816000875af1158015610353573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103779190610a67565b949350505050565b604051638a54c52f60e01b81526001600160a01b0385811660048301526024820185905246604483015283811660648301526084820183905260009190871690638a54c52f9060a4016020604051808303816000875af11580156103e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061040b9190610a80565b9695505050505050565b604080516001808252818301909252600091816020015b606081526020019060019003908161042c57505060408051600180825281830190925291925060009190602082015b606081526020019060019003908161045b579050509050604051806040016040528060088152602001671d1bdc12185d125960c21b815250826000815181106104a6576104a6610ab3565b60200260200101819052506104ba836106c2565b816000815181106104cd576104cd610ab3565b6020026020010181905250336001600160a01b031663468721a785600085856040516024016104fd929190610b1e565b60408051601f198184030181529181526020820180516001600160e01b031663579374b960e11b1790525160e085901b6001600160e01b031916815261054b93929190600090600401610b43565b6020604051808303816000875af115801561056a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058e9190610ba7565b5050505050565b6000806105ac89896105a68a610c85565b896107c3565b91506105bb8585858c8661037f565b905060006105cf60a0890160808a01610913565b6001600160a01b03161461066f576001600160a01b03891663641f776e836105fd60a08b0160808c01610913565b6040516001600160e01b031960e085901b16815260048101929092526001600160a01b031660248201526044016020604051808303816000875af1158015610649573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066d9190610ba7565b505b97509795505050505050565b60005b81811015610292576106b8898585858581811061069d5761069d610ab3565b90506020028101906106af919061098e565b888c8c8c610595565b505060010161067e565b6060816000036106e95750506040805180820190915260018152600360fc1b602082015290565b8160005b811561071357806106fd81610d46565b915061070c9050600a83610d75565b91506106ed565b60008167ffffffffffffffff81111561072e5761072e610a9d565b6040519080825280601f01601f191660200182016040528015610758576020820181803683370190505b5090505b84156103775761076d600183610d89565b915061077a600a86610da2565b610785906030610db6565b60f81b81838151811061079a5761079a610ab3565b60200101906001600160f81b031916908160001a9053506107bc600a86610d75565b945061075c565b6020820151825160608401516040808601519051635829492f60e11b81526000946001600160a01b038a169463b052925e94610809948b948a9283929091600401610dc9565b6020604051808303816000875af1158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c9190610a67565b95945050505050565b60005b83811015610870578181015183820152602001610858565b50506000910152565b60008151808452610891816020860160208601610855565b601f01601f19169290920160200192915050565b6020815260006108b86020830184610879565b9392505050565b6000602082840312156108d157600080fd5b813567ffffffffffffffff8111156108e857600080fd5b820161010081850312156108b857600080fd5b6001600160a01b038116811461091057600080fd5b50565b60006020828403121561092557600080fd5b81356108b8816108fb565b6000808335601e1984360301811261094757600080fd5b83018035915067ffffffffffffffff82111561096257600080fd5b60200191503681900382131561097757600080fd5b9250929050565b8035610989816108fb565b919050565b60008235609e198336030181126109a457600080fd5b9190910192915050565b6000808335601e198436030181126109c557600080fd5b83018035915067ffffffffffffffff8211156109e057600080fd5b6020019150600581901b360382131561097757600080fd5b60008451610a0a818460208901610855565b919091019283525060601b6bffffffffffffffffffffffff19166020820152603401919050565b6001600160a01b0384168152606060208201819052600090610a5590830185610879565b828103604084015261040b8185610879565b600060208284031215610a7957600080fd5b5051919050565b600060208284031215610a9257600080fd5b81516108b8816108fb565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501808196508360051b8101915082860160005b85811015610b11578284038952610aff848351610879565b98850198935090840190600101610ae7565b5091979650505050505050565b604081526000610b316040830185610ac9565b828103602084015261084c8185610ac9565b60018060a01b0385168152836020820152608060408201526000610b6a6080830185610879565b905060028310610b8a57634e487b7160e01b600052602160045260246000fd5b82606083015295945050505050565b801515811461091057600080fd5b600060208284031215610bb957600080fd5b81516108b881610b99565b60405160a0810167ffffffffffffffff81118282101715610be757610be7610a9d565b60405290565b600082601f830112610bfe57600080fd5b813567ffffffffffffffff80821115610c1957610c19610a9d565b604051601f8301601f19908116603f01168101908282118183101715610c4157610c41610a9d565b81604052838152866020858801011115610c5a57600080fd5b836020870160208301376000602085830101528094505050505092915050565b803561098981610b99565b600060a08236031215610c9757600080fd5b610c9f610bc4565b823563ffffffff81168114610cb357600080fd5b8152602083013567ffffffffffffffff80821115610cd057600080fd5b610cdc36838701610bed565b60208401526040850135915080821115610cf557600080fd5b50610d0236828601610bed565b604083015250610d1460608401610c7a565b6060820152610d256080840161097e565b608082015292915050565b634e487b7160e01b600052601160045260246000fd5b600060018201610d5857610d58610d30565b5060010190565b634e487b7160e01b600052601260045260246000fd5b600082610d8457610d84610d5f565b500490565b81810381811115610d9c57610d9c610d30565b92915050565b600082610db157610db1610d5f565b500690565b80820180821115610d9c57610d9c610d30565b87815260e060208201526000610de260e0830189610879565b63ffffffff881660408401526001600160a01b0387811660608501528616608084015284151560a084015282810360c0840152610e1f8185610879565b9a995050505050505050505056fea264697066735822122040470770e7f603d20cdea8118401756a0349e1cdc776519095ccf844ef03c2cd64736f6c63430008130033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c8063a3f4df7e1461003b578063c1bce50714610080575b600080fd5b61006a6040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b81525081565b60405161007791906108a5565b60405180910390f35b61009361008e3660046108bf565b610095565b005b600061009f61029d565b9050600061013c6100b36020850185610913565b6100c06080860186610930565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506101029250505060a0870187610930565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061030192505050565b905060006101776101536060860160408701610913565b6101636040870160208801610913565b856101716020890189610913565b8661037f565b905061019261018c6080860160608701610913565b83610415565b60006101d96101a46020870187610913565b846101b260c089018961098e565b856101c360608b0160408c01610913565b6101d360408c0160208d01610913565b8a610595565b5090506102216101ec6020870187610913565b6101fc6060880160408901610913565b61020c6040890160208a01610913565b87868661021c60e08d018d6109ae565b61067b565b61022e6020860186610913565b6040516329287c1b60e21b8152600481018590523060248201523360448201526001600160a01b03919091169063a4a1f06c90606401600060405180830381600087803b15801561027e57600080fd5b505af1158015610292573d6000803e3d6000fd5b505050505050505050565b60008046905060006040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b81525082306040516020016102e2939291906109f8565b60408051601f1981840301815291905280516020909101209392505050565b604051631a64dfad60e01b81526000906001600160a01b03851690631a64dfad9061033490309087908790600401610a31565b6020604051808303816000875af1158015610353573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103779190610a67565b949350505050565b604051638a54c52f60e01b81526001600160a01b0385811660048301526024820185905246604483015283811660648301526084820183905260009190871690638a54c52f9060a4016020604051808303816000875af11580156103e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061040b9190610a80565b9695505050505050565b604080516001808252818301909252600091816020015b606081526020019060019003908161042c57505060408051600180825281830190925291925060009190602082015b606081526020019060019003908161045b579050509050604051806040016040528060088152602001671d1bdc12185d125960c21b815250826000815181106104a6576104a6610ab3565b60200260200101819052506104ba836106c2565b816000815181106104cd576104cd610ab3565b6020026020010181905250336001600160a01b031663468721a785600085856040516024016104fd929190610b1e565b60408051601f198184030181529181526020820180516001600160e01b031663579374b960e11b1790525160e085901b6001600160e01b031916815261054b93929190600090600401610b43565b6020604051808303816000875af115801561056a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058e9190610ba7565b5050505050565b6000806105ac89896105a68a610c85565b896107c3565b91506105bb8585858c8661037f565b905060006105cf60a0890160808a01610913565b6001600160a01b03161461066f576001600160a01b03891663641f776e836105fd60a08b0160808c01610913565b6040516001600160e01b031960e085901b16815260048101929092526001600160a01b031660248201526044016020604051808303816000875af1158015610649573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066d9190610ba7565b505b97509795505050505050565b60005b81811015610292576106b8898585858581811061069d5761069d610ab3565b90506020028101906106af919061098e565b888c8c8c610595565b505060010161067e565b6060816000036106e95750506040805180820190915260018152600360fc1b602082015290565b8160005b811561071357806106fd81610d46565b915061070c9050600a83610d75565b91506106ed565b60008167ffffffffffffffff81111561072e5761072e610a9d565b6040519080825280601f01601f191660200182016040528015610758576020820181803683370190505b5090505b84156103775761076d600183610d89565b915061077a600a86610da2565b610785906030610db6565b60f81b81838151811061079a5761079a610ab3565b60200101906001600160f81b031916908160001a9053506107bc600a86610d75565b945061075c565b6020820151825160608401516040808601519051635829492f60e11b81526000946001600160a01b038a169463b052925e94610809948b948a9283929091600401610dc9565b6020604051808303816000875af1158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c9190610a67565b95945050505050565b60005b83811015610870578181015183820152602001610858565b50506000910152565b60008151808452610891816020860160208601610855565b601f01601f19169290920160200192915050565b6020815260006108b86020830184610879565b9392505050565b6000602082840312156108d157600080fd5b813567ffffffffffffffff8111156108e857600080fd5b820161010081850312156108b857600080fd5b6001600160a01b038116811461091057600080fd5b50565b60006020828403121561092557600080fd5b81356108b8816108fb565b6000808335601e1984360301811261094757600080fd5b83018035915067ffffffffffffffff82111561096257600080fd5b60200191503681900382131561097757600080fd5b9250929050565b8035610989816108fb565b919050565b60008235609e198336030181126109a457600080fd5b9190910192915050565b6000808335601e198436030181126109c557600080fd5b83018035915067ffffffffffffffff8211156109e057600080fd5b6020019150600581901b360382131561097757600080fd5b60008451610a0a818460208901610855565b919091019283525060601b6bffffffffffffffffffffffff19166020820152603401919050565b6001600160a01b0384168152606060208201819052600090610a5590830185610879565b828103604084015261040b8185610879565b600060208284031215610a7957600080fd5b5051919050565b600060208284031215610a9257600080fd5b81516108b8816108fb565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501808196508360051b8101915082860160005b85811015610b11578284038952610aff848351610879565b98850198935090840190600101610ae7565b5091979650505050505050565b604081526000610b316040830185610ac9565b828103602084015261084c8185610ac9565b60018060a01b0385168152836020820152608060408201526000610b6a6080830185610879565b905060028310610b8a57634e487b7160e01b600052602160045260246000fd5b82606083015295945050505050565b801515811461091057600080fd5b600060208284031215610bb957600080fd5b81516108b881610b99565b60405160a0810167ffffffffffffffff81118282101715610be757610be7610a9d565b60405290565b600082601f830112610bfe57600080fd5b813567ffffffffffffffff80821115610c1957610c19610a9d565b604051601f8301601f19908116603f01168101908282118183101715610c4157610c41610a9d565b81604052838152866020858801011115610c5a57600080fd5b836020870160208301376000602085830101528094505050505092915050565b803561098981610b99565b600060a08236031215610c9757600080fd5b610c9f610bc4565b823563ffffffff81168114610cb357600080fd5b8152602083013567ffffffffffffffff80821115610cd057600080fd5b610cdc36838701610bed565b60208401526040850135915080821115610cf557600080fd5b50610d0236828601610bed565b604083015250610d1460608401610c7a565b6060820152610d256080840161097e565b608082015292915050565b634e487b7160e01b600052601160045260246000fd5b600060018201610d5857610d58610d30565b5060010190565b634e487b7160e01b600052601260045260246000fd5b600082610d8457610d84610d5f565b500490565b81810381811115610d9c57610d9c610d30565b92915050565b600082610db157610db1610d5f565b500690565b80820180821115610d9c57610d9c610d30565b87815260e060208201526000610de260e0830189610879565b63ffffffff881660408401526001600160a01b0387811660608501528616608084015284151560a084015282810360c0840152610e1f8185610879565b9a995050505050505050505056fea264697066735822122040470770e7f603d20cdea8118401756a0349e1cdc776519095ccf844ef03c2cd64736f6c63430008130033", + "numDeployments": 2, + "solcInputHash": "512807b5d71481c693c202ae23158904", + "metadata": "{\"compiler\":{\"version\":\"0.8.19+commit.7dd6d404\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"NAME\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contract IHats\",\"name\":\"hatsProtocol\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"hatsAccountImplementation\",\"type\":\"address\"},{\"internalType\":\"contract IERC6551Registry\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"keyValuePairs\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"topHatDetails\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"topHatImageURI\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxSupply\",\"type\":\"uint32\"},{\"internalType\":\"string\",\"name\":\"details\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"imageURI\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isMutable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"wearer\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"contract ISablierV2LockupLinear\",\"name\":\"sablier\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint128\",\"name\":\"totalAmount\",\"type\":\"uint128\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"cancelable\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"transferable\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"uint40\",\"name\":\"start\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"cliff\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"end\",\"type\":\"uint40\"}],\"internalType\":\"struct LockupLinear.Timestamps\",\"name\":\"timestamps\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"}],\"internalType\":\"struct LockupLinear.Broker\",\"name\":\"broker\",\"type\":\"tuple\"}],\"internalType\":\"struct DecentHats_0_1_0.SablierStreamParams[]\",\"name\":\"sablierParams\",\"type\":\"tuple[]\"}],\"internalType\":\"struct DecentHats_0_1_0.Hat\",\"name\":\"adminHat\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxSupply\",\"type\":\"uint32\"},{\"internalType\":\"string\",\"name\":\"details\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"imageURI\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isMutable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"wearer\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"contract ISablierV2LockupLinear\",\"name\":\"sablier\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint128\",\"name\":\"totalAmount\",\"type\":\"uint128\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"cancelable\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"transferable\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"uint40\",\"name\":\"start\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"cliff\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"end\",\"type\":\"uint40\"}],\"internalType\":\"struct LockupLinear.Timestamps\",\"name\":\"timestamps\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"}],\"internalType\":\"struct LockupLinear.Broker\",\"name\":\"broker\",\"type\":\"tuple\"}],\"internalType\":\"struct DecentHats_0_1_0.SablierStreamParams[]\",\"name\":\"sablierParams\",\"type\":\"tuple[]\"}],\"internalType\":\"struct DecentHats_0_1_0.Hat[]\",\"name\":\"hats\",\"type\":\"tuple[]\"}],\"internalType\":\"struct DecentHats_0_1_0.CreateTreeParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"createAndDeclareTree\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/DecentHats_0_1_0.sol\":\"DecentHats_0_1_0\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.7.0 <0.9.0;\\n\\n/// @title Enum - Collection of enums\\n/// @author Richard Meissner - \\ncontract Enum {\\n enum Operation {Call, DelegateCall}\\n}\\n\",\"keccak256\":\"0x473e45b1a5cc47be494b0e123c9127f0c11c1e0992a321ae5a644c0bfdb2c14f\",\"license\":\"LGPL-3.0-only\"},\"@gnosis.pm/zodiac/contracts/interfaces/IAvatar.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\n\\n/// @title Zodiac Avatar - A contract that manages modules that can execute transactions via this contract.\\npragma solidity >=0.7.0 <0.9.0;\\n\\nimport \\\"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\\\";\\n\\ninterface IAvatar {\\n event EnabledModule(address module);\\n event DisabledModule(address module);\\n event ExecutionFromModuleSuccess(address indexed module);\\n event ExecutionFromModuleFailure(address indexed module);\\n\\n /// @dev Enables a module on the avatar.\\n /// @notice Can only be called by the avatar.\\n /// @notice Modules should be stored as a linked list.\\n /// @notice Must emit EnabledModule(address module) if successful.\\n /// @param module Module to be enabled.\\n function enableModule(address module) external;\\n\\n /// @dev Disables a module on the avatar.\\n /// @notice Can only be called by the avatar.\\n /// @notice Must emit DisabledModule(address module) if successful.\\n /// @param prevModule Address that pointed to the module to be removed in the linked list\\n /// @param module Module to be removed.\\n function disableModule(address prevModule, address module) external;\\n\\n /// @dev Allows a Module to execute a transaction.\\n /// @notice Can only be called by an enabled module.\\n /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.\\n /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.\\n /// @param to Destination address of module transaction.\\n /// @param value Ether value of module transaction.\\n /// @param data Data payload of module transaction.\\n /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.\\n function execTransactionFromModule(\\n address to,\\n uint256 value,\\n bytes memory data,\\n Enum.Operation operation\\n ) external returns (bool success);\\n\\n /// @dev Allows a Module to execute a transaction and return data\\n /// @notice Can only be called by an enabled module.\\n /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.\\n /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.\\n /// @param to Destination address of module transaction.\\n /// @param value Ether value of module transaction.\\n /// @param data Data payload of module transaction.\\n /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.\\n function execTransactionFromModuleReturnData(\\n address to,\\n uint256 value,\\n bytes memory data,\\n Enum.Operation operation\\n ) external returns (bool success, bytes memory returnData);\\n\\n /// @dev Returns if an module is enabled\\n /// @return True if the module is enabled\\n function isModuleEnabled(address module) external view returns (bool);\\n\\n /// @dev Returns array of modules.\\n /// @param start Start of the page.\\n /// @param pageSize Maximum number of modules that should be returned.\\n /// @return array Array of modules.\\n /// @return next Start of the next page.\\n function getModulesPaginated(address start, uint256 pageSize)\\n external\\n view\\n returns (address[] memory array, address next);\\n}\\n\",\"keccak256\":\"0xcd5508ffe596eef8fbccfd5fc4f10a34397773547ce64e212d48b5212865ec1f\",\"license\":\"LGPL-3.0-only\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n}\\n\",\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\"},\"contracts/DecentHats_0_1_0.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity =0.8.19;\\n\\nimport {Enum} from \\\"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\\\";\\nimport {IAvatar} from \\\"@gnosis.pm/zodiac/contracts/interfaces/IAvatar.sol\\\";\\nimport {Strings} from \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {IERC6551Registry} from \\\"./interfaces/IERC6551Registry.sol\\\";\\nimport {IHats} from \\\"./interfaces/hats/IHats.sol\\\";\\nimport {ISablierV2LockupLinear} from \\\"./interfaces/sablier/ISablierV2LockupLinear.sol\\\";\\nimport {LockupLinear} from \\\"./interfaces/sablier/LockupLinear.sol\\\";\\n\\ncontract DecentHats_0_1_0 {\\n string public constant NAME = \\\"DecentHats_0_1_0\\\";\\n\\n struct SablierStreamParams {\\n ISablierV2LockupLinear sablier;\\n address sender;\\n uint128 totalAmount;\\n address asset;\\n bool cancelable;\\n bool transferable;\\n LockupLinear.Timestamps timestamps;\\n LockupLinear.Broker broker;\\n }\\n\\n struct Hat {\\n uint32 maxSupply;\\n string details;\\n string imageURI;\\n bool isMutable;\\n address wearer;\\n SablierStreamParams[] sablierParams; // Optional Sablier stream parameters\\n }\\n\\n struct CreateTreeParams {\\n IHats hatsProtocol;\\n address hatsAccountImplementation;\\n IERC6551Registry registry;\\n address keyValuePairs;\\n string topHatDetails;\\n string topHatImageURI;\\n Hat adminHat;\\n Hat[] hats;\\n }\\n\\n function getSalt() internal view returns (bytes32 salt) {\\n uint256 chainId;\\n assembly {\\n chainId := chainid()\\n }\\n\\n bytes memory concatenatedSaltInput = abi.encodePacked(\\n NAME,\\n chainId,\\n address(this)\\n );\\n\\n salt = keccak256(concatenatedSaltInput);\\n }\\n\\n function updateKeyValuePairs(\\n address _keyValuePairs,\\n uint256 topHatId\\n ) internal {\\n string[] memory keys = new string[](1);\\n string[] memory values = new string[](1);\\n keys[0] = \\\"topHatId\\\";\\n values[0] = Strings.toString(topHatId);\\n\\n IAvatar(msg.sender).execTransactionFromModule(\\n _keyValuePairs,\\n 0,\\n abi.encodeWithSignature(\\n \\\"updateValues(string[],string[])\\\",\\n keys,\\n values\\n ),\\n Enum.Operation.Call\\n );\\n }\\n\\n function createHat(\\n IHats _hatsProtocol,\\n uint256 adminHatId,\\n Hat memory _hat,\\n address topHatAccount\\n ) internal returns (uint256) {\\n return\\n _hatsProtocol.createHat(\\n adminHatId,\\n _hat.details,\\n _hat.maxSupply,\\n topHatAccount,\\n topHatAccount,\\n _hat.isMutable,\\n _hat.imageURI\\n );\\n }\\n\\n function createAccount(\\n IERC6551Registry _registry,\\n address _hatsAccountImplementation,\\n bytes32 salt,\\n address protocolAddress,\\n uint256 hatId\\n ) internal returns (address) {\\n return\\n _registry.createAccount(\\n _hatsAccountImplementation,\\n salt,\\n block.chainid,\\n protocolAddress,\\n hatId\\n );\\n }\\n\\n function createTopHatAndAccount(\\n IHats _hatsProtocol,\\n string memory _topHatDetails,\\n string memory _topHatImageURI,\\n IERC6551Registry _registry,\\n address _hatsAccountImplementation,\\n bytes32 salt\\n ) internal returns (uint256 topHatId, address topHatAccount) {\\n topHatId = _hatsProtocol.mintTopHat(\\n address(this),\\n _topHatDetails,\\n _topHatImageURI\\n );\\n\\n topHatAccount = createAccount(\\n _registry,\\n _hatsAccountImplementation,\\n salt,\\n address(_hatsProtocol),\\n topHatId\\n );\\n }\\n\\n function createHatAndAccountAndMintAndStreams(\\n IHats hatsProtocol,\\n uint256 adminHatId,\\n Hat calldata hat,\\n address topHatAccount,\\n IERC6551Registry registry,\\n address hatsAccountImplementation,\\n bytes32 salt\\n ) internal returns (uint256 hatId, address accountAddress) {\\n hatId = createHat(hatsProtocol, adminHatId, hat, topHatAccount);\\n\\n accountAddress = createAccount(\\n registry,\\n hatsAccountImplementation,\\n salt,\\n address(hatsProtocol),\\n hatId\\n );\\n\\n if (hat.wearer != address(0)) {\\n hatsProtocol.mintHat(hatId, hat.wearer);\\n }\\n\\n for (uint256 i = 0; i < hat.sablierParams.length; ) {\\n SablierStreamParams memory sablierParams = hat.sablierParams[i];\\n\\n // Approve tokens for Sablier\\n IAvatar(msg.sender).execTransactionFromModule(\\n sablierParams.asset,\\n 0,\\n abi.encodeWithSignature(\\n \\\"approve(address,uint256)\\\",\\n address(sablierParams.sablier),\\n sablierParams.totalAmount\\n ),\\n Enum.Operation.Call\\n );\\n\\n LockupLinear.CreateWithTimestamps memory params = LockupLinear\\n .CreateWithTimestamps({\\n sender: sablierParams.sender,\\n recipient: accountAddress,\\n totalAmount: sablierParams.totalAmount,\\n asset: IERC20(sablierParams.asset),\\n cancelable: sablierParams.cancelable,\\n transferable: sablierParams.transferable,\\n timestamps: sablierParams.timestamps,\\n broker: sablierParams.broker\\n });\\n\\n // Proxy the Sablier call through IAvatar\\n IAvatar(msg.sender).execTransactionFromModule(\\n address(sablierParams.sablier),\\n 0,\\n abi.encodeWithSignature(\\n \\\"createWithTimestamps((address,address,uint128,address,bool,bool,(uint40,uint40,uint40),(address,uint256)))\\\",\\n params\\n ),\\n Enum.Operation.Call\\n );\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n function createAndDeclareTree(CreateTreeParams calldata params) public {\\n bytes32 salt = getSalt();\\n\\n (uint256 topHatId, address topHatAccount) = createTopHatAndAccount(\\n params.hatsProtocol,\\n params.topHatDetails,\\n params.topHatImageURI,\\n params.registry,\\n params.hatsAccountImplementation,\\n salt\\n );\\n\\n updateKeyValuePairs(params.keyValuePairs, topHatId);\\n\\n (uint256 adminHatId, ) = createHatAndAccountAndMintAndStreams(\\n params.hatsProtocol,\\n topHatId,\\n params.adminHat,\\n topHatAccount,\\n params.registry,\\n params.hatsAccountImplementation,\\n salt\\n );\\n\\n for (uint256 i = 0; i < params.hats.length; ) {\\n createHatAndAccountAndMintAndStreams(\\n params.hatsProtocol,\\n adminHatId,\\n params.hats[i],\\n topHatAccount,\\n params.registry,\\n params.hatsAccountImplementation,\\n salt\\n );\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n params.hatsProtocol.transferHat(topHatId, address(this), msg.sender);\\n }\\n}\\n\",\"keccak256\":\"0xdc0d2b3c556d675f26152895a17e1fb76c91d1a85b2689cf435fb3666381ac41\",\"license\":\"MIT\"},\"contracts/interfaces/IERC6551Registry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IERC6551Registry {\\n /**\\n * @dev Creates a token bound account for a non-fungible token.\\n *\\n * If account has already been created, returns the account address without calling create2.\\n *\\n * Emits ERC6551AccountCreated event.\\n *\\n * @return account The address of the token bound account\\n */\\n function createAccount(\\n address implementation,\\n bytes32 salt,\\n uint256 chainId,\\n address tokenContract,\\n uint256 tokenId\\n ) external returns (address account);\\n}\\n\",\"keccak256\":\"0x64c52de8a8e68398e61dd8b42dda8e9af8cf6abf93bb85629c322440991ea568\",\"license\":\"MIT\"},\"contracts/interfaces/hats/IHats.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0\\n// Copyright (C) 2023 Haberdasher Labs\\n//\\n// This program is free software: you can redistribute it and/or modify\\n// it under the terms of the GNU Affero General Public License as published by\\n// the Free Software Foundation, either version 3 of the License, or\\n// (at your option) any later version.\\n//\\n// This program is distributed in the hope that it will be useful,\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\\n// GNU Affero General Public License for more details.\\n//\\n// You should have received a copy of the GNU Affero General Public License\\n// along with this program. If not, see .\\n\\npragma solidity >=0.8.13;\\n\\ninterface IHats {\\n function mintTopHat(\\n address _target,\\n string memory _details,\\n string memory _imageURI\\n ) external returns (uint256 topHatId);\\n\\n function createHat(\\n uint256 _admin,\\n string calldata _details,\\n uint32 _maxSupply,\\n address _eligibility,\\n address _toggle,\\n bool _mutable,\\n string calldata _imageURI\\n ) external returns (uint256 newHatId);\\n\\n function mintHat(\\n uint256 _hatId,\\n address _wearer\\n ) external returns (bool success);\\n\\n function transferHat(uint256 _hatId, address _from, address _to) external;\\n}\\n\",\"keccak256\":\"0x8e35022f5c0fcf0059033abec78ec890f0cf3bbac09d6d24051cff9679239511\",\"license\":\"AGPL-3.0\"},\"contracts/interfaces/sablier/ISablierV2LockupLinear.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {LockupLinear} from \\\"./LockupLinear.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface ISablierV2LockupLinear {\\n function createWithTimestamps(\\n LockupLinear.CreateWithTimestamps calldata params\\n ) external returns (uint256 streamId);\\n}\\n\",\"keccak256\":\"0xf4899637eb2e6c76c35e2d201e56e162a50e6bc7b5b9156e00866f0703ad07ca\",\"license\":\"MIT\"},\"contracts/interfaces/sablier/LockupLinear.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LockupLinear {\\n struct CreateWithTimestamps {\\n address sender;\\n address recipient;\\n uint128 totalAmount;\\n IERC20 asset;\\n bool cancelable;\\n bool transferable;\\n Timestamps timestamps;\\n Broker broker;\\n }\\n\\n struct Timestamps {\\n uint40 start;\\n uint40 cliff;\\n uint40 end;\\n }\\n\\n struct Broker {\\n address account;\\n uint256 fee;\\n }\\n}\\n\",\"keccak256\":\"0x497fdb52b5e1a5a7e0711a9f7d5fb036eb668ccb92ea908ee088f56ee08a4ce8\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50611477806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80638c5f591a1461003b578063a3f4df7e14610050575b600080fd5b61004e610049366004610ac2565b610095565b005b61007f6040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b81525081565b60405161008c9190610b54565b60405180910390f35b600061009f6102cd565b905060008061015e6100b46020860186610b7f565b6100c16080870187610b9c565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506101039250505060a0880188610b9c565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610148925050506060890160408a01610b7f565b61015860408a0160208b01610b7f565b88610331565b909250905061017c6101766080860160608701610b7f565b836103c3565b60006101c361018e6020870187610b7f565b8461019c60c0890189610bf9565b856101ad60608b0160408c01610b7f565b6101bd60408c0160208d01610b7f565b8a610543565b50905060005b6101d660e0870187610c19565b9050811015610250576102466101ef6020880188610b7f565b836101fd60e08a018a610c19565b8581811061020d5761020d610c62565b905060200281019061021f9190610bf9565b8661023060608c0160408d01610b7f565b61024060408d0160208e01610b7f565b8b610543565b50506001016101c9565b5061025e6020860186610b7f565b6040516329287c1b60e21b8152600481018590523060248201523360448201526001600160a01b03919091169063a4a1f06c90606401600060405180830381600087803b1580156102ae57600080fd5b505af11580156102c2573d6000803e3d6000fd5b505050505050505050565b60008046905060006040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b815250823060405160200161031293929190610c78565b60408051601f1981840301815291905280516020909101209392505050565b600080876001600160a01b0316631a64dfad3089896040518463ffffffff1660e01b815260040161036493929190610cb1565b6020604051808303816000875af1158015610383573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a79190610ce7565b91506103b68585858b86610892565b9050965096945050505050565b604080516001808252818301909252600091816020015b60608152602001906001900390816103da57505060408051600180825281830190925291925060009190602082015b6060815260200190600190039081610409579050509050604051806040016040528060088152602001671d1bdc12185d125960c21b8152508260008151811061045457610454610c62565b602002602001018190525061046883610928565b8160008151811061047b5761047b610c62565b6020026020010181905250336001600160a01b031663468721a785600085856040516024016104ab929190610d6b565b60408051601f198184030181529181526020820180516001600160e01b031663579374b960e11b1790525160e085901b6001600160e01b03191681526104f993929190600090600401610d90565b6020604051808303816000875af1158015610518573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053c9190610df4565b5050505050565b60008061055a89896105548a61113b565b89610a30565b91506105698585858c86610892565b9050600061057d60a0890160808a01610b7f565b6001600160a01b03161461061d576001600160a01b03891663641f776e836105ab60a08b0160808c01610b7f565b6040516001600160e01b031960e085901b16815260048101929092526001600160a01b031660248201526044016020604051808303816000875af11580156105f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061b9190610df4565b505b60005b61062d60a08901896111ff565b905081101561088557600061064560a08a018a6111ff565b8381811061065557610655610c62565b9050610160020180360381019061066c9190611248565b6060810151815160408084015190516001600160a01b0390921660248301526001600160801b03166044820152919250339163468721a7919060009060640160408051601f198184030181529181526020820180516001600160e01b031663095ea7b360e01b1790525160e085901b6001600160e01b03191681526106f993929190600090600401610d90565b6020604051808303816000875af1158015610718573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073c9190610df4565b50600060405180610100016040528083602001516001600160a01b03168152602001856001600160a01b0316815260200183604001516001600160801b0316815260200183606001516001600160a01b031681526020018360800151151581526020018360a00151151581526020018360c0015181526020018360e001518152509050336001600160a01b031663468721a783600001516000846040516024016107e69190611265565b60408051601f198184030181529181526020820180516001600160e01b03166353b1572760e01b1790525160e085901b6001600160e01b031916815261083493929190600090600401610d90565b6020604051808303816000875af1158015610853573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108779190610df4565b508260010192505050610620565b5097509795505050505050565b604051638a54c52f60e01b81526001600160a01b0385811660048301526024820185905246604483015283811660648301526084820183905260009190871690638a54c52f9060a4016020604051808303816000875af11580156108fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091e9190611327565b9695505050505050565b60608160000361094f5750506040805180820190915260018152600360fc1b602082015290565b8160005b811561097957806109638161135a565b91506109729050600a83611389565b9150610953565b6000816001600160401b0381111561099357610993610d00565b6040519080825280601f01601f1916602001820160405280156109bd576020820181803683370190505b5090505b8415610a28576109d260018361139d565b91506109df600a866113b6565b6109ea9060306113ca565b60f81b8183815181106109ff576109ff610c62565b60200101906001600160f81b031916908160001a905350610a21600a86611389565b94506109c1565b949350505050565b6020820151825160608401516040808601519051635829492f60e11b81526000946001600160a01b038a169463b052925e94610a76948b948a92839290916004016113dd565b6020604051808303816000875af1158015610a95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab99190610ce7565b95945050505050565b600060208284031215610ad457600080fd5b81356001600160401b03811115610aea57600080fd5b82016101008185031215610afd57600080fd5b9392505050565b60005b83811015610b1f578181015183820152602001610b07565b50506000910152565b60008151808452610b40816020860160208601610b04565b601f01601f19169290920160200192915050565b602081526000610afd6020830184610b28565b6001600160a01b0381168114610b7c57600080fd5b50565b600060208284031215610b9157600080fd5b8135610afd81610b67565b6000808335601e19843603018112610bb357600080fd5b8301803591506001600160401b03821115610bcd57600080fd5b602001915036819003821315610be257600080fd5b9250929050565b8035610bf481610b67565b919050565b6000823560be19833603018112610c0f57600080fd5b9190910192915050565b6000808335601e19843603018112610c3057600080fd5b8301803591506001600160401b03821115610c4a57600080fd5b6020019150600581901b3603821315610be257600080fd5b634e487b7160e01b600052603260045260246000fd5b60008451610c8a818460208901610b04565b919091019283525060601b6bffffffffffffffffffffffff19166020820152603401919050565b6001600160a01b0384168152606060208201819052600090610cd590830185610b28565b828103604084015261091e8185610b28565b600060208284031215610cf957600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b600081518084526020808501808196508360051b8101915082860160005b85811015610d5e578284038952610d4c848351610b28565b98850198935090840190600101610d34565b5091979650505050505050565b604081526000610d7e6040830185610d16565b8281036020840152610ab98185610d16565b60018060a01b0385168152836020820152608060408201526000610db76080830185610b28565b905060028310610dd757634e487b7160e01b600052602160045260246000fd5b82606083015295945050505050565b8015158114610b7c57600080fd5b600060208284031215610e0657600080fd5b8151610afd81610de6565b60405160c081016001600160401b0381118282101715610e3357610e33610d00565b60405290565b604051601f8201601f191681016001600160401b0381118282101715610e6157610e61610d00565b604052919050565b803563ffffffff81168114610bf457600080fd5b600082601f830112610e8e57600080fd5b81356001600160401b03811115610ea757610ea7610d00565b610eba601f8201601f1916602001610e39565b818152846020838601011115610ecf57600080fd5b816020850160208301376000918101602001919091529392505050565b8035610bf481610de6565b80356001600160801b0381168114610bf457600080fd5b803564ffffffffff81168114610bf457600080fd5b600060608284031215610f3557600080fd5b604051606081018181106001600160401b0382111715610f5757610f57610d00565b604052905080610f6683610f0e565b8152610f7460208401610f0e565b6020820152610f8560408401610f0e565b60408201525092915050565b600060408284031215610fa357600080fd5b604051604081018181106001600160401b0382111715610fc557610fc5610d00565b6040529050808235610fd681610b67565b8152602092830135920191909152919050565b60006101608284031215610ffc57600080fd5b60405161010081018181106001600160401b038211171561101f5761101f610d00565b60405290508061102e83610be9565b815261103c60208401610be9565b602082015261104d60408401610ef7565b604082015261105e60608401610be9565b606082015261106f60808401610eec565b608082015261108060a08401610eec565b60a08201526110928460c08501610f23565b60c08201526110a5846101208501610f91565b60e08201525092915050565b600082601f8301126110c257600080fd5b813560206001600160401b038211156110dd576110dd610d00565b6110eb818360051b01610e39565b828152610160928302850182019282820191908785111561110b57600080fd5b8387015b8581101561112e576111218982610fe9565b845292840192810161110f565b5090979650505050505050565b600060c0823603121561114d57600080fd5b611155610e11565b61115e83610e69565b815260208301356001600160401b038082111561117a57600080fd5b61118636838701610e7d565b6020840152604085013591508082111561119f57600080fd5b6111ab36838701610e7d565b60408401526111bc60608601610eec565b60608401526111cd60808601610be9565b608084015260a08501359150808211156111e657600080fd5b506111f3368286016110b1565b60a08301525092915050565b6000808335601e1984360301811261121657600080fd5b8301803591506001600160401b0382111561123057600080fd5b602001915061016081023603821315610be257600080fd5b6000610160828403121561125b57600080fd5b610afd8383610fe9565b81516001600160a01b0390811682526020808401518216908301526040808401516001600160801b031690830152606080840151909116908201526080808301516101608301916112b99084018215159052565b5060a08301516112cd60a084018215159052565b5060c083015161130060c0840182805164ffffffffff908116835260208083015182169084015260409182015116910152565b5060e0929092015180516001600160a01b0316610120830152602001516101409091015290565b60006020828403121561133957600080fd5b8151610afd81610b67565b634e487b7160e01b600052601160045260246000fd5b60006001820161136c5761136c611344565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261139857611398611373565b500490565b818103818111156113b0576113b0611344565b92915050565b6000826113c5576113c5611373565b500690565b808201808211156113b0576113b0611344565b87815260e0602082015260006113f660e0830189610b28565b63ffffffff881660408401526001600160a01b0387811660608501528616608084015284151560a084015282810360c08401526114338185610b28565b9a995050505050505050505056fea2646970667358221220d17954ba81bca52da6ca1f1cf74a0e04f2ce3c50651d1d806611eb18ab0d551e64736f6c63430008130033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80638c5f591a1461003b578063a3f4df7e14610050575b600080fd5b61004e610049366004610ac2565b610095565b005b61007f6040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b81525081565b60405161008c9190610b54565b60405180910390f35b600061009f6102cd565b905060008061015e6100b46020860186610b7f565b6100c16080870187610b9c565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506101039250505060a0880188610b9c565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610148925050506060890160408a01610b7f565b61015860408a0160208b01610b7f565b88610331565b909250905061017c6101766080860160608701610b7f565b836103c3565b60006101c361018e6020870187610b7f565b8461019c60c0890189610bf9565b856101ad60608b0160408c01610b7f565b6101bd60408c0160208d01610b7f565b8a610543565b50905060005b6101d660e0870187610c19565b9050811015610250576102466101ef6020880188610b7f565b836101fd60e08a018a610c19565b8581811061020d5761020d610c62565b905060200281019061021f9190610bf9565b8661023060608c0160408d01610b7f565b61024060408d0160208e01610b7f565b8b610543565b50506001016101c9565b5061025e6020860186610b7f565b6040516329287c1b60e21b8152600481018590523060248201523360448201526001600160a01b03919091169063a4a1f06c90606401600060405180830381600087803b1580156102ae57600080fd5b505af11580156102c2573d6000803e3d6000fd5b505050505050505050565b60008046905060006040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b815250823060405160200161031293929190610c78565b60408051601f1981840301815291905280516020909101209392505050565b600080876001600160a01b0316631a64dfad3089896040518463ffffffff1660e01b815260040161036493929190610cb1565b6020604051808303816000875af1158015610383573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a79190610ce7565b91506103b68585858b86610892565b9050965096945050505050565b604080516001808252818301909252600091816020015b60608152602001906001900390816103da57505060408051600180825281830190925291925060009190602082015b6060815260200190600190039081610409579050509050604051806040016040528060088152602001671d1bdc12185d125960c21b8152508260008151811061045457610454610c62565b602002602001018190525061046883610928565b8160008151811061047b5761047b610c62565b6020026020010181905250336001600160a01b031663468721a785600085856040516024016104ab929190610d6b565b60408051601f198184030181529181526020820180516001600160e01b031663579374b960e11b1790525160e085901b6001600160e01b03191681526104f993929190600090600401610d90565b6020604051808303816000875af1158015610518573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053c9190610df4565b5050505050565b60008061055a89896105548a61113b565b89610a30565b91506105698585858c86610892565b9050600061057d60a0890160808a01610b7f565b6001600160a01b03161461061d576001600160a01b03891663641f776e836105ab60a08b0160808c01610b7f565b6040516001600160e01b031960e085901b16815260048101929092526001600160a01b031660248201526044016020604051808303816000875af11580156105f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061b9190610df4565b505b60005b61062d60a08901896111ff565b905081101561088557600061064560a08a018a6111ff565b8381811061065557610655610c62565b9050610160020180360381019061066c9190611248565b6060810151815160408084015190516001600160a01b0390921660248301526001600160801b03166044820152919250339163468721a7919060009060640160408051601f198184030181529181526020820180516001600160e01b031663095ea7b360e01b1790525160e085901b6001600160e01b03191681526106f993929190600090600401610d90565b6020604051808303816000875af1158015610718573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073c9190610df4565b50600060405180610100016040528083602001516001600160a01b03168152602001856001600160a01b0316815260200183604001516001600160801b0316815260200183606001516001600160a01b031681526020018360800151151581526020018360a00151151581526020018360c0015181526020018360e001518152509050336001600160a01b031663468721a783600001516000846040516024016107e69190611265565b60408051601f198184030181529181526020820180516001600160e01b03166353b1572760e01b1790525160e085901b6001600160e01b031916815261083493929190600090600401610d90565b6020604051808303816000875af1158015610853573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108779190610df4565b508260010192505050610620565b5097509795505050505050565b604051638a54c52f60e01b81526001600160a01b0385811660048301526024820185905246604483015283811660648301526084820183905260009190871690638a54c52f9060a4016020604051808303816000875af11580156108fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091e9190611327565b9695505050505050565b60608160000361094f5750506040805180820190915260018152600360fc1b602082015290565b8160005b811561097957806109638161135a565b91506109729050600a83611389565b9150610953565b6000816001600160401b0381111561099357610993610d00565b6040519080825280601f01601f1916602001820160405280156109bd576020820181803683370190505b5090505b8415610a28576109d260018361139d565b91506109df600a866113b6565b6109ea9060306113ca565b60f81b8183815181106109ff576109ff610c62565b60200101906001600160f81b031916908160001a905350610a21600a86611389565b94506109c1565b949350505050565b6020820151825160608401516040808601519051635829492f60e11b81526000946001600160a01b038a169463b052925e94610a76948b948a92839290916004016113dd565b6020604051808303816000875af1158015610a95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab99190610ce7565b95945050505050565b600060208284031215610ad457600080fd5b81356001600160401b03811115610aea57600080fd5b82016101008185031215610afd57600080fd5b9392505050565b60005b83811015610b1f578181015183820152602001610b07565b50506000910152565b60008151808452610b40816020860160208601610b04565b601f01601f19169290920160200192915050565b602081526000610afd6020830184610b28565b6001600160a01b0381168114610b7c57600080fd5b50565b600060208284031215610b9157600080fd5b8135610afd81610b67565b6000808335601e19843603018112610bb357600080fd5b8301803591506001600160401b03821115610bcd57600080fd5b602001915036819003821315610be257600080fd5b9250929050565b8035610bf481610b67565b919050565b6000823560be19833603018112610c0f57600080fd5b9190910192915050565b6000808335601e19843603018112610c3057600080fd5b8301803591506001600160401b03821115610c4a57600080fd5b6020019150600581901b3603821315610be257600080fd5b634e487b7160e01b600052603260045260246000fd5b60008451610c8a818460208901610b04565b919091019283525060601b6bffffffffffffffffffffffff19166020820152603401919050565b6001600160a01b0384168152606060208201819052600090610cd590830185610b28565b828103604084015261091e8185610b28565b600060208284031215610cf957600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b600081518084526020808501808196508360051b8101915082860160005b85811015610d5e578284038952610d4c848351610b28565b98850198935090840190600101610d34565b5091979650505050505050565b604081526000610d7e6040830185610d16565b8281036020840152610ab98185610d16565b60018060a01b0385168152836020820152608060408201526000610db76080830185610b28565b905060028310610dd757634e487b7160e01b600052602160045260246000fd5b82606083015295945050505050565b8015158114610b7c57600080fd5b600060208284031215610e0657600080fd5b8151610afd81610de6565b60405160c081016001600160401b0381118282101715610e3357610e33610d00565b60405290565b604051601f8201601f191681016001600160401b0381118282101715610e6157610e61610d00565b604052919050565b803563ffffffff81168114610bf457600080fd5b600082601f830112610e8e57600080fd5b81356001600160401b03811115610ea757610ea7610d00565b610eba601f8201601f1916602001610e39565b818152846020838601011115610ecf57600080fd5b816020850160208301376000918101602001919091529392505050565b8035610bf481610de6565b80356001600160801b0381168114610bf457600080fd5b803564ffffffffff81168114610bf457600080fd5b600060608284031215610f3557600080fd5b604051606081018181106001600160401b0382111715610f5757610f57610d00565b604052905080610f6683610f0e565b8152610f7460208401610f0e565b6020820152610f8560408401610f0e565b60408201525092915050565b600060408284031215610fa357600080fd5b604051604081018181106001600160401b0382111715610fc557610fc5610d00565b6040529050808235610fd681610b67565b8152602092830135920191909152919050565b60006101608284031215610ffc57600080fd5b60405161010081018181106001600160401b038211171561101f5761101f610d00565b60405290508061102e83610be9565b815261103c60208401610be9565b602082015261104d60408401610ef7565b604082015261105e60608401610be9565b606082015261106f60808401610eec565b608082015261108060a08401610eec565b60a08201526110928460c08501610f23565b60c08201526110a5846101208501610f91565b60e08201525092915050565b600082601f8301126110c257600080fd5b813560206001600160401b038211156110dd576110dd610d00565b6110eb818360051b01610e39565b828152610160928302850182019282820191908785111561110b57600080fd5b8387015b8581101561112e576111218982610fe9565b845292840192810161110f565b5090979650505050505050565b600060c0823603121561114d57600080fd5b611155610e11565b61115e83610e69565b815260208301356001600160401b038082111561117a57600080fd5b61118636838701610e7d565b6020840152604085013591508082111561119f57600080fd5b6111ab36838701610e7d565b60408401526111bc60608601610eec565b60608401526111cd60808601610be9565b608084015260a08501359150808211156111e657600080fd5b506111f3368286016110b1565b60a08301525092915050565b6000808335601e1984360301811261121657600080fd5b8301803591506001600160401b0382111561123057600080fd5b602001915061016081023603821315610be257600080fd5b6000610160828403121561125b57600080fd5b610afd8383610fe9565b81516001600160a01b0390811682526020808401518216908301526040808401516001600160801b031690830152606080840151909116908201526080808301516101608301916112b99084018215159052565b5060a08301516112cd60a084018215159052565b5060c083015161130060c0840182805164ffffffffff908116835260208083015182169084015260409182015116910152565b5060e0929092015180516001600160a01b0316610120830152602001516101409091015290565b60006020828403121561133957600080fd5b8151610afd81610b67565b634e487b7160e01b600052601160045260246000fd5b60006001820161136c5761136c611344565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261139857611398611373565b500490565b818103818111156113b0576113b0611344565b92915050565b6000826113c5576113c5611373565b500690565b808201808211156113b0576113b0611344565b87815260e0602082015260006113f660e0830189610b28565b63ffffffff881660408401526001600160a01b0387811660608501528616608084015284151560a084015282810360c08401526114338185610b28565b9a995050505050505050505056fea2646970667358221220d17954ba81bca52da6ca1f1cf74a0e04f2ce3c50651d1d806611eb18ab0d551e64736f6c63430008130033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/polygon/solcInputs/512807b5d71481c693c202ae23158904.json b/deployments/polygon/solcInputs/512807b5d71481c693c202ae23158904.json new file mode 100644 index 00000000..0d0d55c8 --- /dev/null +++ b/deployments/polygon/solcInputs/512807b5d71481c693c202ae23158904.json @@ -0,0 +1,59 @@ +{ + "language": "Solidity", + "sources": { + "@gnosis.pm/safe-contracts/contracts/common/Enum.sol": { + "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.0 <0.9.0;\n\n/// @title Enum - Collection of enums\n/// @author Richard Meissner - \ncontract Enum {\n enum Operation {Call, DelegateCall}\n}\n" + }, + "@gnosis.pm/zodiac/contracts/interfaces/IAvatar.sol": { + "content": "// SPDX-License-Identifier: LGPL-3.0-only\n\n/// @title Zodiac Avatar - A contract that manages modules that can execute transactions via this contract.\npragma solidity >=0.7.0 <0.9.0;\n\nimport \"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\";\n\ninterface IAvatar {\n event EnabledModule(address module);\n event DisabledModule(address module);\n event ExecutionFromModuleSuccess(address indexed module);\n event ExecutionFromModuleFailure(address indexed module);\n\n /// @dev Enables a module on the avatar.\n /// @notice Can only be called by the avatar.\n /// @notice Modules should be stored as a linked list.\n /// @notice Must emit EnabledModule(address module) if successful.\n /// @param module Module to be enabled.\n function enableModule(address module) external;\n\n /// @dev Disables a module on the avatar.\n /// @notice Can only be called by the avatar.\n /// @notice Must emit DisabledModule(address module) if successful.\n /// @param prevModule Address that pointed to the module to be removed in the linked list\n /// @param module Module to be removed.\n function disableModule(address prevModule, address module) external;\n\n /// @dev Allows a Module to execute a transaction.\n /// @notice Can only be called by an enabled module.\n /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.\n /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.\n /// @param to Destination address of module transaction.\n /// @param value Ether value of module transaction.\n /// @param data Data payload of module transaction.\n /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.\n function execTransactionFromModule(\n address to,\n uint256 value,\n bytes memory data,\n Enum.Operation operation\n ) external returns (bool success);\n\n /// @dev Allows a Module to execute a transaction and return data\n /// @notice Can only be called by an enabled module.\n /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.\n /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.\n /// @param to Destination address of module transaction.\n /// @param value Ether value of module transaction.\n /// @param data Data payload of module transaction.\n /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.\n function execTransactionFromModuleReturnData(\n address to,\n uint256 value,\n bytes memory data,\n Enum.Operation operation\n ) external returns (bool success, bytes memory returnData);\n\n /// @dev Returns if an module is enabled\n /// @return True if the module is enabled\n function isModuleEnabled(address module) external view returns (bool);\n\n /// @dev Returns array of modules.\n /// @param start Start of the page.\n /// @param pageSize Maximum number of modules that should be returned.\n /// @return array Array of modules.\n /// @return next Start of the next page.\n function getModulesPaginated(address start, uint256 pageSize)\n external\n view\n returns (address[] memory array, address next);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp >>= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n" + }, + "contracts/DecentHats_0_1_0.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity =0.8.19;\n\nimport {Enum} from \"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\";\nimport {IAvatar} from \"@gnosis.pm/zodiac/contracts/interfaces/IAvatar.sol\";\nimport {Strings} from \"@openzeppelin/contracts/utils/Strings.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {IERC6551Registry} from \"./interfaces/IERC6551Registry.sol\";\nimport {IHats} from \"./interfaces/hats/IHats.sol\";\nimport {ISablierV2LockupLinear} from \"./interfaces/sablier/ISablierV2LockupLinear.sol\";\nimport {LockupLinear} from \"./interfaces/sablier/LockupLinear.sol\";\n\ncontract DecentHats_0_1_0 {\n string public constant NAME = \"DecentHats_0_1_0\";\n\n struct SablierStreamParams {\n ISablierV2LockupLinear sablier;\n address sender;\n uint128 totalAmount;\n address asset;\n bool cancelable;\n bool transferable;\n LockupLinear.Timestamps timestamps;\n LockupLinear.Broker broker;\n }\n\n struct Hat {\n uint32 maxSupply;\n string details;\n string imageURI;\n bool isMutable;\n address wearer;\n SablierStreamParams[] sablierParams; // Optional Sablier stream parameters\n }\n\n struct CreateTreeParams {\n IHats hatsProtocol;\n address hatsAccountImplementation;\n IERC6551Registry registry;\n address keyValuePairs;\n string topHatDetails;\n string topHatImageURI;\n Hat adminHat;\n Hat[] hats;\n }\n\n function getSalt() internal view returns (bytes32 salt) {\n uint256 chainId;\n assembly {\n chainId := chainid()\n }\n\n bytes memory concatenatedSaltInput = abi.encodePacked(\n NAME,\n chainId,\n address(this)\n );\n\n salt = keccak256(concatenatedSaltInput);\n }\n\n function updateKeyValuePairs(\n address _keyValuePairs,\n uint256 topHatId\n ) internal {\n string[] memory keys = new string[](1);\n string[] memory values = new string[](1);\n keys[0] = \"topHatId\";\n values[0] = Strings.toString(topHatId);\n\n IAvatar(msg.sender).execTransactionFromModule(\n _keyValuePairs,\n 0,\n abi.encodeWithSignature(\n \"updateValues(string[],string[])\",\n keys,\n values\n ),\n Enum.Operation.Call\n );\n }\n\n function createHat(\n IHats _hatsProtocol,\n uint256 adminHatId,\n Hat memory _hat,\n address topHatAccount\n ) internal returns (uint256) {\n return\n _hatsProtocol.createHat(\n adminHatId,\n _hat.details,\n _hat.maxSupply,\n topHatAccount,\n topHatAccount,\n _hat.isMutable,\n _hat.imageURI\n );\n }\n\n function createAccount(\n IERC6551Registry _registry,\n address _hatsAccountImplementation,\n bytes32 salt,\n address protocolAddress,\n uint256 hatId\n ) internal returns (address) {\n return\n _registry.createAccount(\n _hatsAccountImplementation,\n salt,\n block.chainid,\n protocolAddress,\n hatId\n );\n }\n\n function createTopHatAndAccount(\n IHats _hatsProtocol,\n string memory _topHatDetails,\n string memory _topHatImageURI,\n IERC6551Registry _registry,\n address _hatsAccountImplementation,\n bytes32 salt\n ) internal returns (uint256 topHatId, address topHatAccount) {\n topHatId = _hatsProtocol.mintTopHat(\n address(this),\n _topHatDetails,\n _topHatImageURI\n );\n\n topHatAccount = createAccount(\n _registry,\n _hatsAccountImplementation,\n salt,\n address(_hatsProtocol),\n topHatId\n );\n }\n\n function createHatAndAccountAndMintAndStreams(\n IHats hatsProtocol,\n uint256 adminHatId,\n Hat calldata hat,\n address topHatAccount,\n IERC6551Registry registry,\n address hatsAccountImplementation,\n bytes32 salt\n ) internal returns (uint256 hatId, address accountAddress) {\n hatId = createHat(hatsProtocol, adminHatId, hat, topHatAccount);\n\n accountAddress = createAccount(\n registry,\n hatsAccountImplementation,\n salt,\n address(hatsProtocol),\n hatId\n );\n\n if (hat.wearer != address(0)) {\n hatsProtocol.mintHat(hatId, hat.wearer);\n }\n\n for (uint256 i = 0; i < hat.sablierParams.length; ) {\n SablierStreamParams memory sablierParams = hat.sablierParams[i];\n\n // Approve tokens for Sablier\n IAvatar(msg.sender).execTransactionFromModule(\n sablierParams.asset,\n 0,\n abi.encodeWithSignature(\n \"approve(address,uint256)\",\n address(sablierParams.sablier),\n sablierParams.totalAmount\n ),\n Enum.Operation.Call\n );\n\n LockupLinear.CreateWithTimestamps memory params = LockupLinear\n .CreateWithTimestamps({\n sender: sablierParams.sender,\n recipient: accountAddress,\n totalAmount: sablierParams.totalAmount,\n asset: IERC20(sablierParams.asset),\n cancelable: sablierParams.cancelable,\n transferable: sablierParams.transferable,\n timestamps: sablierParams.timestamps,\n broker: sablierParams.broker\n });\n\n // Proxy the Sablier call through IAvatar\n IAvatar(msg.sender).execTransactionFromModule(\n address(sablierParams.sablier),\n 0,\n abi.encodeWithSignature(\n \"createWithTimestamps((address,address,uint128,address,bool,bool,(uint40,uint40,uint40),(address,uint256)))\",\n params\n ),\n Enum.Operation.Call\n );\n\n unchecked {\n ++i;\n }\n }\n }\n\n function createAndDeclareTree(CreateTreeParams calldata params) public {\n bytes32 salt = getSalt();\n\n (uint256 topHatId, address topHatAccount) = createTopHatAndAccount(\n params.hatsProtocol,\n params.topHatDetails,\n params.topHatImageURI,\n params.registry,\n params.hatsAccountImplementation,\n salt\n );\n\n updateKeyValuePairs(params.keyValuePairs, topHatId);\n\n (uint256 adminHatId, ) = createHatAndAccountAndMintAndStreams(\n params.hatsProtocol,\n topHatId,\n params.adminHat,\n topHatAccount,\n params.registry,\n params.hatsAccountImplementation,\n salt\n );\n\n for (uint256 i = 0; i < params.hats.length; ) {\n createHatAndAccountAndMintAndStreams(\n params.hatsProtocol,\n adminHatId,\n params.hats[i],\n topHatAccount,\n params.registry,\n params.hatsAccountImplementation,\n salt\n );\n\n unchecked {\n ++i;\n }\n }\n\n params.hatsProtocol.transferHat(topHatId, address(this), msg.sender);\n }\n}\n" + }, + "contracts/interfaces/hats/IHats.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0\n// Copyright (C) 2023 Haberdasher Labs\n//\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU Affero General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU Affero General Public License for more details.\n//\n// You should have received a copy of the GNU Affero General Public License\n// along with this program. If not, see .\n\npragma solidity >=0.8.13;\n\ninterface IHats {\n function mintTopHat(\n address _target,\n string memory _details,\n string memory _imageURI\n ) external returns (uint256 topHatId);\n\n function createHat(\n uint256 _admin,\n string calldata _details,\n uint32 _maxSupply,\n address _eligibility,\n address _toggle,\n bool _mutable,\n string calldata _imageURI\n ) external returns (uint256 newHatId);\n\n function mintHat(\n uint256 _hatId,\n address _wearer\n ) external returns (bool success);\n\n function transferHat(uint256 _hatId, address _from, address _to) external;\n}\n" + }, + "contracts/interfaces/IERC6551Registry.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\ninterface IERC6551Registry {\n /**\n * @dev Creates a token bound account for a non-fungible token.\n *\n * If account has already been created, returns the account address without calling create2.\n *\n * Emits ERC6551AccountCreated event.\n *\n * @return account The address of the token bound account\n */\n function createAccount(\n address implementation,\n bytes32 salt,\n uint256 chainId,\n address tokenContract,\n uint256 tokenId\n ) external returns (address account);\n}\n" + }, + "contracts/interfaces/sablier/ISablierV2LockupLinear.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {LockupLinear} from \"./LockupLinear.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface ISablierV2LockupLinear {\n function createWithTimestamps(\n LockupLinear.CreateWithTimestamps calldata params\n ) external returns (uint256 streamId);\n}\n" + }, + "contracts/interfaces/sablier/LockupLinear.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LockupLinear {\n struct CreateWithTimestamps {\n address sender;\n address recipient;\n uint128 totalAmount;\n IERC20 asset;\n bool cancelable;\n bool transferable;\n Timestamps timestamps;\n Broker broker;\n }\n\n struct Timestamps {\n uint40 start;\n uint40 cliff;\n uint40 end;\n }\n\n struct Broker {\n address account;\n uint256 fee;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/deployments/sepolia/DecentHats_0_1_0.json b/deployments/sepolia/DecentHats_0_1_0.json index 57855553..e60e4085 100644 --- a/deployments/sepolia/DecentHats_0_1_0.json +++ b/deployments/sepolia/DecentHats_0_1_0.json @@ -1,5 +1,5 @@ { - "address": "0xC2631745541DC73654C43DfAB6693a47dA91dd1c", + "address": "0x8250B3b8BcD854750B0ACdEE7298C6626D6ba9b9", "abi": [ { "inputs": [], @@ -74,6 +74,82 @@ "internalType": "address", "name": "wearer", "type": "address" + }, + { + "components": [ + { + "internalType": "contract ISablierV2LockupLinear", + "name": "sablier", + "type": "address" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint128", + "name": "totalAmount", + "type": "uint128" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "bool", + "name": "cancelable", + "type": "bool" + }, + { + "internalType": "bool", + "name": "transferable", + "type": "bool" + }, + { + "components": [ + { + "internalType": "uint40", + "name": "start", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "cliff", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "end", + "type": "uint40" + } + ], + "internalType": "struct LockupLinear.Timestamps", + "name": "timestamps", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "fee", + "type": "uint256" + } + ], + "internalType": "struct LockupLinear.Broker", + "name": "broker", + "type": "tuple" + } + ], + "internalType": "struct DecentHats_0_1_0.SablierStreamParams[]", + "name": "sablierParams", + "type": "tuple[]" } ], "internalType": "struct DecentHats_0_1_0.Hat", @@ -106,6 +182,82 @@ "internalType": "address", "name": "wearer", "type": "address" + }, + { + "components": [ + { + "internalType": "contract ISablierV2LockupLinear", + "name": "sablier", + "type": "address" + }, + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint128", + "name": "totalAmount", + "type": "uint128" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "bool", + "name": "cancelable", + "type": "bool" + }, + { + "internalType": "bool", + "name": "transferable", + "type": "bool" + }, + { + "components": [ + { + "internalType": "uint40", + "name": "start", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "cliff", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "end", + "type": "uint40" + } + ], + "internalType": "struct LockupLinear.Timestamps", + "name": "timestamps", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "fee", + "type": "uint256" + } + ], + "internalType": "struct LockupLinear.Broker", + "name": "broker", + "type": "tuple" + } + ], + "internalType": "struct DecentHats_0_1_0.SablierStreamParams[]", + "name": "sablierParams", + "type": "tuple[]" } ], "internalType": "struct DecentHats_0_1_0.Hat[]", @@ -124,28 +276,28 @@ "type": "function" } ], - "transactionHash": "0xa8a1f0032182326b2cabf8d67181a977e3a8d68396d568317d8ef17c25ecf26f", + "transactionHash": "0x42be72ca7992fefb68ef43f7e03262d9592787b97513170a23fa0093c49caff1", "receipt": { "to": null, "from": "0xfcf7a2794D066110162ADdcE3085dfd6221D4ddD", - "contractAddress": "0xC2631745541DC73654C43DfAB6693a47dA91dd1c", - "transactionIndex": 52, - "gasUsed": "848547", + "contractAddress": "0x8250B3b8BcD854750B0ACdEE7298C6626D6ba9b9", + "transactionIndex": 71, + "gasUsed": "1184549", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xdd79195b57df12a6bf0f5da9b37cb4c1933ba3a8b80c0b9e22b7ee3e0d248e3a", - "transactionHash": "0xa8a1f0032182326b2cabf8d67181a977e3a8d68396d568317d8ef17c25ecf26f", + "blockHash": "0x51126bdfcd86505547307e84c6b9a3b13376d1b3e481f1a70a72465283983f5d", + "transactionHash": "0x42be72ca7992fefb68ef43f7e03262d9592787b97513170a23fa0093c49caff1", "logs": [], - "blockNumber": 6280987, - "cumulativeGasUsed": "8952196", + "blockNumber": 6673787, + "cumulativeGasUsed": "8858403", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "88a7dc38a4aa54f89c0bd740dfe90545", - "metadata": "{\"compiler\":{\"version\":\"0.8.19+commit.7dd6d404\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"NAME\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contract IHats\",\"name\":\"hatsProtocol\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"hatsAccountImplementation\",\"type\":\"address\"},{\"internalType\":\"contract IERC6551Registry\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"keyValuePairs\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"topHatDetails\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"topHatImageURI\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxSupply\",\"type\":\"uint32\"},{\"internalType\":\"string\",\"name\":\"details\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"imageURI\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isMutable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"wearer\",\"type\":\"address\"}],\"internalType\":\"struct DecentHats_0_1_0.Hat\",\"name\":\"adminHat\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxSupply\",\"type\":\"uint32\"},{\"internalType\":\"string\",\"name\":\"details\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"imageURI\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isMutable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"wearer\",\"type\":\"address\"}],\"internalType\":\"struct DecentHats_0_1_0.Hat[]\",\"name\":\"hats\",\"type\":\"tuple[]\"}],\"internalType\":\"struct DecentHats_0_1_0.CreateTreeParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"createAndDeclareTree\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/DecentHats_0_1_0.sol\":\"DecentHats_0_1_0\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.7.0 <0.9.0;\\n\\n/// @title Enum - Collection of enums\\n/// @author Richard Meissner - \\ncontract Enum {\\n enum Operation {Call, DelegateCall}\\n}\\n\",\"keccak256\":\"0x473e45b1a5cc47be494b0e123c9127f0c11c1e0992a321ae5a644c0bfdb2c14f\",\"license\":\"LGPL-3.0-only\"},\"@gnosis.pm/zodiac/contracts/interfaces/IAvatar.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\n\\n/// @title Zodiac Avatar - A contract that manages modules that can execute transactions via this contract.\\npragma solidity >=0.7.0 <0.9.0;\\n\\nimport \\\"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\\\";\\n\\ninterface IAvatar {\\n event EnabledModule(address module);\\n event DisabledModule(address module);\\n event ExecutionFromModuleSuccess(address indexed module);\\n event ExecutionFromModuleFailure(address indexed module);\\n\\n /// @dev Enables a module on the avatar.\\n /// @notice Can only be called by the avatar.\\n /// @notice Modules should be stored as a linked list.\\n /// @notice Must emit EnabledModule(address module) if successful.\\n /// @param module Module to be enabled.\\n function enableModule(address module) external;\\n\\n /// @dev Disables a module on the avatar.\\n /// @notice Can only be called by the avatar.\\n /// @notice Must emit DisabledModule(address module) if successful.\\n /// @param prevModule Address that pointed to the module to be removed in the linked list\\n /// @param module Module to be removed.\\n function disableModule(address prevModule, address module) external;\\n\\n /// @dev Allows a Module to execute a transaction.\\n /// @notice Can only be called by an enabled module.\\n /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.\\n /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.\\n /// @param to Destination address of module transaction.\\n /// @param value Ether value of module transaction.\\n /// @param data Data payload of module transaction.\\n /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.\\n function execTransactionFromModule(\\n address to,\\n uint256 value,\\n bytes memory data,\\n Enum.Operation operation\\n ) external returns (bool success);\\n\\n /// @dev Allows a Module to execute a transaction and return data\\n /// @notice Can only be called by an enabled module.\\n /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.\\n /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.\\n /// @param to Destination address of module transaction.\\n /// @param value Ether value of module transaction.\\n /// @param data Data payload of module transaction.\\n /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.\\n function execTransactionFromModuleReturnData(\\n address to,\\n uint256 value,\\n bytes memory data,\\n Enum.Operation operation\\n ) external returns (bool success, bytes memory returnData);\\n\\n /// @dev Returns if an module is enabled\\n /// @return True if the module is enabled\\n function isModuleEnabled(address module) external view returns (bool);\\n\\n /// @dev Returns array of modules.\\n /// @param start Start of the page.\\n /// @param pageSize Maximum number of modules that should be returned.\\n /// @return array Array of modules.\\n /// @return next Start of the next page.\\n function getModulesPaginated(address start, uint256 pageSize)\\n external\\n view\\n returns (address[] memory array, address next);\\n}\\n\",\"keccak256\":\"0xcd5508ffe596eef8fbccfd5fc4f10a34397773547ce64e212d48b5212865ec1f\",\"license\":\"LGPL-3.0-only\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n}\\n\",\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\"},\"contracts/DecentHats_0_1_0.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity =0.8.19;\\n\\nimport {Enum} from \\\"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\\\";\\nimport {IAvatar} from \\\"@gnosis.pm/zodiac/contracts/interfaces/IAvatar.sol\\\";\\nimport {Strings} from \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\nimport {IERC6551Registry} from \\\"./interfaces/IERC6551Registry.sol\\\";\\nimport {IHats} from \\\"./interfaces/hats/IHats.sol\\\";\\n\\ncontract DecentHats_0_1_0 {\\n string public constant NAME = \\\"DecentHats_0_1_0\\\";\\n\\n struct Hat {\\n uint32 maxSupply;\\n string details;\\n string imageURI;\\n bool isMutable;\\n address wearer;\\n }\\n\\n struct CreateTreeParams {\\n IHats hatsProtocol;\\n address hatsAccountImplementation;\\n IERC6551Registry registry;\\n address keyValuePairs;\\n string topHatDetails;\\n string topHatImageURI;\\n Hat adminHat;\\n Hat[] hats;\\n }\\n\\n function getSalt() internal view returns (bytes32 salt) {\\n uint256 chainId;\\n assembly {\\n chainId := chainid()\\n }\\n\\n bytes memory concatenatedSaltInput = abi.encodePacked(\\n NAME,\\n chainId,\\n address(this)\\n );\\n\\n salt = keccak256(concatenatedSaltInput);\\n }\\n\\n function createTopHat(\\n IHats _hatsProtocol,\\n string memory _topHatDetails,\\n string memory _topHatImageURI\\n ) internal returns (uint256) {\\n return\\n _hatsProtocol.mintTopHat(\\n address(this),\\n _topHatDetails,\\n _topHatImageURI\\n );\\n }\\n\\n function createAccount(\\n IERC6551Registry _registry,\\n address _hatsAccountImplementation,\\n bytes32 salt,\\n address protocolAddress,\\n uint256 hatId\\n ) internal returns (address) {\\n return\\n _registry.createAccount(\\n _hatsAccountImplementation,\\n salt,\\n block.chainid,\\n protocolAddress,\\n hatId\\n );\\n }\\n\\n function updateKeyValuePairs(\\n address _keyValuePairs,\\n uint256 topHatId\\n ) internal {\\n string[] memory keys = new string[](1);\\n string[] memory values = new string[](1);\\n keys[0] = \\\"topHatId\\\";\\n values[0] = Strings.toString(topHatId);\\n\\n IAvatar(msg.sender).execTransactionFromModule(\\n _keyValuePairs,\\n 0,\\n abi.encodeWithSignature(\\n \\\"updateValues(string[],string[])\\\",\\n keys,\\n values\\n ),\\n Enum.Operation.Call\\n );\\n }\\n\\n function createHat(\\n IHats _hatsProtocol,\\n uint256 adminHatId,\\n Hat memory _hat,\\n address topHatAccount\\n ) internal returns (uint256) {\\n return\\n _hatsProtocol.createHat(\\n adminHatId,\\n _hat.details,\\n _hat.maxSupply,\\n topHatAccount,\\n topHatAccount,\\n _hat.isMutable,\\n _hat.imageURI\\n );\\n }\\n\\n function createHatAccountMint(\\n IHats hatsProtocol,\\n uint256 adminHatId,\\n Hat calldata hat,\\n address topHatAccount,\\n IERC6551Registry registry,\\n address hatsAccountImplementation,\\n bytes32 salt\\n ) internal returns (uint256 hatId, address accountAddress) {\\n hatId = createHat(hatsProtocol, adminHatId, hat, topHatAccount);\\n\\n accountAddress = createAccount(\\n registry,\\n hatsAccountImplementation,\\n salt,\\n address(hatsProtocol),\\n hatId\\n );\\n\\n if (hat.wearer != address(0)) {\\n hatsProtocol.mintHat(hatId, hat.wearer);\\n }\\n }\\n\\n function handleHats(\\n IHats _hatsProtocol,\\n IERC6551Registry _registry,\\n address _hatsAccountImplementation,\\n bytes32 salt,\\n address topHatAccount,\\n uint256 adminHatId,\\n Hat[] calldata _hats\\n ) internal {\\n for (uint256 i = 0; i < _hats.length; ) {\\n createHatAccountMint(\\n _hatsProtocol,\\n adminHatId,\\n _hats[i],\\n topHatAccount,\\n _registry,\\n _hatsAccountImplementation,\\n salt\\n );\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n function createAndDeclareTree(CreateTreeParams calldata params) public {\\n bytes32 salt = getSalt();\\n uint256 topHatId = createTopHat(\\n params.hatsProtocol,\\n params.topHatDetails,\\n params.topHatImageURI\\n );\\n address topHatAccount = createAccount(\\n params.registry,\\n params.hatsAccountImplementation,\\n salt,\\n address(params.hatsProtocol),\\n topHatId\\n );\\n\\n updateKeyValuePairs(params.keyValuePairs, topHatId);\\n\\n (uint256 adminHatId, ) = createHatAccountMint(\\n params.hatsProtocol,\\n topHatId,\\n params.adminHat,\\n topHatAccount,\\n params.registry,\\n params.hatsAccountImplementation,\\n salt\\n );\\n\\n handleHats(\\n params.hatsProtocol,\\n params.registry,\\n params.hatsAccountImplementation,\\n salt,\\n topHatAccount,\\n adminHatId,\\n params.hats\\n );\\n\\n params.hatsProtocol.transferHat(topHatId, address(this), msg.sender);\\n }\\n}\\n\",\"keccak256\":\"0xd7dbbda48b0f7eedeef3882aab51e93c4881a47bcb09b2f9a20989d22259f027\",\"license\":\"MIT\"},\"contracts/interfaces/IERC6551Registry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IERC6551Registry {\\n /**\\n * @dev Creates a token bound account for a non-fungible token.\\n *\\n * If account has already been created, returns the account address without calling create2.\\n *\\n * Emits ERC6551AccountCreated event.\\n *\\n * @return account The address of the token bound account\\n */\\n function createAccount(\\n address implementation,\\n bytes32 salt,\\n uint256 chainId,\\n address tokenContract,\\n uint256 tokenId\\n ) external returns (address account);\\n}\\n\",\"keccak256\":\"0x64c52de8a8e68398e61dd8b42dda8e9af8cf6abf93bb85629c322440991ea568\",\"license\":\"MIT\"},\"contracts/interfaces/hats/IHats.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0\\n// Copyright (C) 2023 Haberdasher Labs\\n//\\n// This program is free software: you can redistribute it and/or modify\\n// it under the terms of the GNU Affero General Public License as published by\\n// the Free Software Foundation, either version 3 of the License, or\\n// (at your option) any later version.\\n//\\n// This program is distributed in the hope that it will be useful,\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\\n// GNU Affero General Public License for more details.\\n//\\n// You should have received a copy of the GNU Affero General Public License\\n// along with this program. If not, see .\\n\\npragma solidity >=0.8.13;\\n\\ninterface IHats {\\n function mintTopHat(\\n address _target,\\n string memory _details,\\n string memory _imageURI\\n ) external returns (uint256 topHatId);\\n\\n function createHat(\\n uint256 _admin,\\n string calldata _details,\\n uint32 _maxSupply,\\n address _eligibility,\\n address _toggle,\\n bool _mutable,\\n string calldata _imageURI\\n ) external returns (uint256 newHatId);\\n\\n function mintHat(\\n uint256 _hatId,\\n address _wearer\\n ) external returns (bool success);\\n\\n function transferHat(uint256 _hatId, address _from, address _to) external;\\n}\\n\",\"keccak256\":\"0x8e35022f5c0fcf0059033abec78ec890f0cf3bbac09d6d24051cff9679239511\",\"license\":\"AGPL-3.0\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50610e63806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063a3f4df7e1461003b578063c1bce50714610080575b600080fd5b61006a6040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b81525081565b60405161007791906108a5565b60405180910390f35b61009361008e3660046108bf565b610095565b005b600061009f61029d565b9050600061013c6100b36020850185610913565b6100c06080860186610930565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506101029250505060a0870187610930565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061030192505050565b905060006101776101536060860160408701610913565b6101636040870160208801610913565b856101716020890189610913565b8661037f565b905061019261018c6080860160608701610913565b83610415565b60006101d96101a46020870187610913565b846101b260c089018961098e565b856101c360608b0160408c01610913565b6101d360408c0160208d01610913565b8a610595565b5090506102216101ec6020870187610913565b6101fc6060880160408901610913565b61020c6040890160208a01610913565b87868661021c60e08d018d6109ae565b61067b565b61022e6020860186610913565b6040516329287c1b60e21b8152600481018590523060248201523360448201526001600160a01b03919091169063a4a1f06c90606401600060405180830381600087803b15801561027e57600080fd5b505af1158015610292573d6000803e3d6000fd5b505050505050505050565b60008046905060006040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b81525082306040516020016102e2939291906109f8565b60408051601f1981840301815291905280516020909101209392505050565b604051631a64dfad60e01b81526000906001600160a01b03851690631a64dfad9061033490309087908790600401610a31565b6020604051808303816000875af1158015610353573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103779190610a67565b949350505050565b604051638a54c52f60e01b81526001600160a01b0385811660048301526024820185905246604483015283811660648301526084820183905260009190871690638a54c52f9060a4016020604051808303816000875af11580156103e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061040b9190610a80565b9695505050505050565b604080516001808252818301909252600091816020015b606081526020019060019003908161042c57505060408051600180825281830190925291925060009190602082015b606081526020019060019003908161045b579050509050604051806040016040528060088152602001671d1bdc12185d125960c21b815250826000815181106104a6576104a6610ab3565b60200260200101819052506104ba836106c2565b816000815181106104cd576104cd610ab3565b6020026020010181905250336001600160a01b031663468721a785600085856040516024016104fd929190610b1e565b60408051601f198184030181529181526020820180516001600160e01b031663579374b960e11b1790525160e085901b6001600160e01b031916815261054b93929190600090600401610b43565b6020604051808303816000875af115801561056a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058e9190610ba7565b5050505050565b6000806105ac89896105a68a610c85565b896107c3565b91506105bb8585858c8661037f565b905060006105cf60a0890160808a01610913565b6001600160a01b03161461066f576001600160a01b03891663641f776e836105fd60a08b0160808c01610913565b6040516001600160e01b031960e085901b16815260048101929092526001600160a01b031660248201526044016020604051808303816000875af1158015610649573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066d9190610ba7565b505b97509795505050505050565b60005b81811015610292576106b8898585858581811061069d5761069d610ab3565b90506020028101906106af919061098e565b888c8c8c610595565b505060010161067e565b6060816000036106e95750506040805180820190915260018152600360fc1b602082015290565b8160005b811561071357806106fd81610d46565b915061070c9050600a83610d75565b91506106ed565b60008167ffffffffffffffff81111561072e5761072e610a9d565b6040519080825280601f01601f191660200182016040528015610758576020820181803683370190505b5090505b84156103775761076d600183610d89565b915061077a600a86610da2565b610785906030610db6565b60f81b81838151811061079a5761079a610ab3565b60200101906001600160f81b031916908160001a9053506107bc600a86610d75565b945061075c565b6020820151825160608401516040808601519051635829492f60e11b81526000946001600160a01b038a169463b052925e94610809948b948a9283929091600401610dc9565b6020604051808303816000875af1158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c9190610a67565b95945050505050565b60005b83811015610870578181015183820152602001610858565b50506000910152565b60008151808452610891816020860160208601610855565b601f01601f19169290920160200192915050565b6020815260006108b86020830184610879565b9392505050565b6000602082840312156108d157600080fd5b813567ffffffffffffffff8111156108e857600080fd5b820161010081850312156108b857600080fd5b6001600160a01b038116811461091057600080fd5b50565b60006020828403121561092557600080fd5b81356108b8816108fb565b6000808335601e1984360301811261094757600080fd5b83018035915067ffffffffffffffff82111561096257600080fd5b60200191503681900382131561097757600080fd5b9250929050565b8035610989816108fb565b919050565b60008235609e198336030181126109a457600080fd5b9190910192915050565b6000808335601e198436030181126109c557600080fd5b83018035915067ffffffffffffffff8211156109e057600080fd5b6020019150600581901b360382131561097757600080fd5b60008451610a0a818460208901610855565b919091019283525060601b6bffffffffffffffffffffffff19166020820152603401919050565b6001600160a01b0384168152606060208201819052600090610a5590830185610879565b828103604084015261040b8185610879565b600060208284031215610a7957600080fd5b5051919050565b600060208284031215610a9257600080fd5b81516108b8816108fb565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501808196508360051b8101915082860160005b85811015610b11578284038952610aff848351610879565b98850198935090840190600101610ae7565b5091979650505050505050565b604081526000610b316040830185610ac9565b828103602084015261084c8185610ac9565b60018060a01b0385168152836020820152608060408201526000610b6a6080830185610879565b905060028310610b8a57634e487b7160e01b600052602160045260246000fd5b82606083015295945050505050565b801515811461091057600080fd5b600060208284031215610bb957600080fd5b81516108b881610b99565b60405160a0810167ffffffffffffffff81118282101715610be757610be7610a9d565b60405290565b600082601f830112610bfe57600080fd5b813567ffffffffffffffff80821115610c1957610c19610a9d565b604051601f8301601f19908116603f01168101908282118183101715610c4157610c41610a9d565b81604052838152866020858801011115610c5a57600080fd5b836020870160208301376000602085830101528094505050505092915050565b803561098981610b99565b600060a08236031215610c9757600080fd5b610c9f610bc4565b823563ffffffff81168114610cb357600080fd5b8152602083013567ffffffffffffffff80821115610cd057600080fd5b610cdc36838701610bed565b60208401526040850135915080821115610cf557600080fd5b50610d0236828601610bed565b604083015250610d1460608401610c7a565b6060820152610d256080840161097e565b608082015292915050565b634e487b7160e01b600052601160045260246000fd5b600060018201610d5857610d58610d30565b5060010190565b634e487b7160e01b600052601260045260246000fd5b600082610d8457610d84610d5f565b500490565b81810381811115610d9c57610d9c610d30565b92915050565b600082610db157610db1610d5f565b500690565b80820180821115610d9c57610d9c610d30565b87815260e060208201526000610de260e0830189610879565b63ffffffff881660408401526001600160a01b0387811660608501528616608084015284151560a084015282810360c0840152610e1f8185610879565b9a995050505050505050505056fea264697066735822122040470770e7f603d20cdea8118401756a0349e1cdc776519095ccf844ef03c2cd64736f6c63430008130033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c8063a3f4df7e1461003b578063c1bce50714610080575b600080fd5b61006a6040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b81525081565b60405161007791906108a5565b60405180910390f35b61009361008e3660046108bf565b610095565b005b600061009f61029d565b9050600061013c6100b36020850185610913565b6100c06080860186610930565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506101029250505060a0870187610930565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061030192505050565b905060006101776101536060860160408701610913565b6101636040870160208801610913565b856101716020890189610913565b8661037f565b905061019261018c6080860160608701610913565b83610415565b60006101d96101a46020870187610913565b846101b260c089018961098e565b856101c360608b0160408c01610913565b6101d360408c0160208d01610913565b8a610595565b5090506102216101ec6020870187610913565b6101fc6060880160408901610913565b61020c6040890160208a01610913565b87868661021c60e08d018d6109ae565b61067b565b61022e6020860186610913565b6040516329287c1b60e21b8152600481018590523060248201523360448201526001600160a01b03919091169063a4a1f06c90606401600060405180830381600087803b15801561027e57600080fd5b505af1158015610292573d6000803e3d6000fd5b505050505050505050565b60008046905060006040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b81525082306040516020016102e2939291906109f8565b60408051601f1981840301815291905280516020909101209392505050565b604051631a64dfad60e01b81526000906001600160a01b03851690631a64dfad9061033490309087908790600401610a31565b6020604051808303816000875af1158015610353573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103779190610a67565b949350505050565b604051638a54c52f60e01b81526001600160a01b0385811660048301526024820185905246604483015283811660648301526084820183905260009190871690638a54c52f9060a4016020604051808303816000875af11580156103e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061040b9190610a80565b9695505050505050565b604080516001808252818301909252600091816020015b606081526020019060019003908161042c57505060408051600180825281830190925291925060009190602082015b606081526020019060019003908161045b579050509050604051806040016040528060088152602001671d1bdc12185d125960c21b815250826000815181106104a6576104a6610ab3565b60200260200101819052506104ba836106c2565b816000815181106104cd576104cd610ab3565b6020026020010181905250336001600160a01b031663468721a785600085856040516024016104fd929190610b1e565b60408051601f198184030181529181526020820180516001600160e01b031663579374b960e11b1790525160e085901b6001600160e01b031916815261054b93929190600090600401610b43565b6020604051808303816000875af115801561056a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058e9190610ba7565b5050505050565b6000806105ac89896105a68a610c85565b896107c3565b91506105bb8585858c8661037f565b905060006105cf60a0890160808a01610913565b6001600160a01b03161461066f576001600160a01b03891663641f776e836105fd60a08b0160808c01610913565b6040516001600160e01b031960e085901b16815260048101929092526001600160a01b031660248201526044016020604051808303816000875af1158015610649573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061066d9190610ba7565b505b97509795505050505050565b60005b81811015610292576106b8898585858581811061069d5761069d610ab3565b90506020028101906106af919061098e565b888c8c8c610595565b505060010161067e565b6060816000036106e95750506040805180820190915260018152600360fc1b602082015290565b8160005b811561071357806106fd81610d46565b915061070c9050600a83610d75565b91506106ed565b60008167ffffffffffffffff81111561072e5761072e610a9d565b6040519080825280601f01601f191660200182016040528015610758576020820181803683370190505b5090505b84156103775761076d600183610d89565b915061077a600a86610da2565b610785906030610db6565b60f81b81838151811061079a5761079a610ab3565b60200101906001600160f81b031916908160001a9053506107bc600a86610d75565b945061075c565b6020820151825160608401516040808601519051635829492f60e11b81526000946001600160a01b038a169463b052925e94610809948b948a9283929091600401610dc9565b6020604051808303816000875af1158015610828573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061084c9190610a67565b95945050505050565b60005b83811015610870578181015183820152602001610858565b50506000910152565b60008151808452610891816020860160208601610855565b601f01601f19169290920160200192915050565b6020815260006108b86020830184610879565b9392505050565b6000602082840312156108d157600080fd5b813567ffffffffffffffff8111156108e857600080fd5b820161010081850312156108b857600080fd5b6001600160a01b038116811461091057600080fd5b50565b60006020828403121561092557600080fd5b81356108b8816108fb565b6000808335601e1984360301811261094757600080fd5b83018035915067ffffffffffffffff82111561096257600080fd5b60200191503681900382131561097757600080fd5b9250929050565b8035610989816108fb565b919050565b60008235609e198336030181126109a457600080fd5b9190910192915050565b6000808335601e198436030181126109c557600080fd5b83018035915067ffffffffffffffff8211156109e057600080fd5b6020019150600581901b360382131561097757600080fd5b60008451610a0a818460208901610855565b919091019283525060601b6bffffffffffffffffffffffff19166020820152603401919050565b6001600160a01b0384168152606060208201819052600090610a5590830185610879565b828103604084015261040b8185610879565b600060208284031215610a7957600080fd5b5051919050565b600060208284031215610a9257600080fd5b81516108b8816108fb565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b600081518084526020808501808196508360051b8101915082860160005b85811015610b11578284038952610aff848351610879565b98850198935090840190600101610ae7565b5091979650505050505050565b604081526000610b316040830185610ac9565b828103602084015261084c8185610ac9565b60018060a01b0385168152836020820152608060408201526000610b6a6080830185610879565b905060028310610b8a57634e487b7160e01b600052602160045260246000fd5b82606083015295945050505050565b801515811461091057600080fd5b600060208284031215610bb957600080fd5b81516108b881610b99565b60405160a0810167ffffffffffffffff81118282101715610be757610be7610a9d565b60405290565b600082601f830112610bfe57600080fd5b813567ffffffffffffffff80821115610c1957610c19610a9d565b604051601f8301601f19908116603f01168101908282118183101715610c4157610c41610a9d565b81604052838152866020858801011115610c5a57600080fd5b836020870160208301376000602085830101528094505050505092915050565b803561098981610b99565b600060a08236031215610c9757600080fd5b610c9f610bc4565b823563ffffffff81168114610cb357600080fd5b8152602083013567ffffffffffffffff80821115610cd057600080fd5b610cdc36838701610bed565b60208401526040850135915080821115610cf557600080fd5b50610d0236828601610bed565b604083015250610d1460608401610c7a565b6060820152610d256080840161097e565b608082015292915050565b634e487b7160e01b600052601160045260246000fd5b600060018201610d5857610d58610d30565b5060010190565b634e487b7160e01b600052601260045260246000fd5b600082610d8457610d84610d5f565b500490565b81810381811115610d9c57610d9c610d30565b92915050565b600082610db157610db1610d5f565b500690565b80820180821115610d9c57610d9c610d30565b87815260e060208201526000610de260e0830189610879565b63ffffffff881660408401526001600160a01b0387811660608501528616608084015284151560a084015282810360c0840152610e1f8185610879565b9a995050505050505050505056fea264697066735822122040470770e7f603d20cdea8118401756a0349e1cdc776519095ccf844ef03c2cd64736f6c63430008130033", + "numDeployments": 4, + "solcInputHash": "512807b5d71481c693c202ae23158904", + "metadata": "{\"compiler\":{\"version\":\"0.8.19+commit.7dd6d404\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"NAME\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contract IHats\",\"name\":\"hatsProtocol\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"hatsAccountImplementation\",\"type\":\"address\"},{\"internalType\":\"contract IERC6551Registry\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"keyValuePairs\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"topHatDetails\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"topHatImageURI\",\"type\":\"string\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxSupply\",\"type\":\"uint32\"},{\"internalType\":\"string\",\"name\":\"details\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"imageURI\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isMutable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"wearer\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"contract ISablierV2LockupLinear\",\"name\":\"sablier\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint128\",\"name\":\"totalAmount\",\"type\":\"uint128\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"cancelable\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"transferable\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"uint40\",\"name\":\"start\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"cliff\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"end\",\"type\":\"uint40\"}],\"internalType\":\"struct LockupLinear.Timestamps\",\"name\":\"timestamps\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"}],\"internalType\":\"struct LockupLinear.Broker\",\"name\":\"broker\",\"type\":\"tuple\"}],\"internalType\":\"struct DecentHats_0_1_0.SablierStreamParams[]\",\"name\":\"sablierParams\",\"type\":\"tuple[]\"}],\"internalType\":\"struct DecentHats_0_1_0.Hat\",\"name\":\"adminHat\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"maxSupply\",\"type\":\"uint32\"},{\"internalType\":\"string\",\"name\":\"details\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"imageURI\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isMutable\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"wearer\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"contract ISablierV2LockupLinear\",\"name\":\"sablier\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint128\",\"name\":\"totalAmount\",\"type\":\"uint128\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"cancelable\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"transferable\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"uint40\",\"name\":\"start\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"cliff\",\"type\":\"uint40\"},{\"internalType\":\"uint40\",\"name\":\"end\",\"type\":\"uint40\"}],\"internalType\":\"struct LockupLinear.Timestamps\",\"name\":\"timestamps\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"}],\"internalType\":\"struct LockupLinear.Broker\",\"name\":\"broker\",\"type\":\"tuple\"}],\"internalType\":\"struct DecentHats_0_1_0.SablierStreamParams[]\",\"name\":\"sablierParams\",\"type\":\"tuple[]\"}],\"internalType\":\"struct DecentHats_0_1_0.Hat[]\",\"name\":\"hats\",\"type\":\"tuple[]\"}],\"internalType\":\"struct DecentHats_0_1_0.CreateTreeParams\",\"name\":\"params\",\"type\":\"tuple\"}],\"name\":\"createAndDeclareTree\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/DecentHats_0_1_0.sol\":\"DecentHats_0_1_0\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\npragma solidity >=0.7.0 <0.9.0;\\n\\n/// @title Enum - Collection of enums\\n/// @author Richard Meissner - \\ncontract Enum {\\n enum Operation {Call, DelegateCall}\\n}\\n\",\"keccak256\":\"0x473e45b1a5cc47be494b0e123c9127f0c11c1e0992a321ae5a644c0bfdb2c14f\",\"license\":\"LGPL-3.0-only\"},\"@gnosis.pm/zodiac/contracts/interfaces/IAvatar.sol\":{\"content\":\"// SPDX-License-Identifier: LGPL-3.0-only\\n\\n/// @title Zodiac Avatar - A contract that manages modules that can execute transactions via this contract.\\npragma solidity >=0.7.0 <0.9.0;\\n\\nimport \\\"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\\\";\\n\\ninterface IAvatar {\\n event EnabledModule(address module);\\n event DisabledModule(address module);\\n event ExecutionFromModuleSuccess(address indexed module);\\n event ExecutionFromModuleFailure(address indexed module);\\n\\n /// @dev Enables a module on the avatar.\\n /// @notice Can only be called by the avatar.\\n /// @notice Modules should be stored as a linked list.\\n /// @notice Must emit EnabledModule(address module) if successful.\\n /// @param module Module to be enabled.\\n function enableModule(address module) external;\\n\\n /// @dev Disables a module on the avatar.\\n /// @notice Can only be called by the avatar.\\n /// @notice Must emit DisabledModule(address module) if successful.\\n /// @param prevModule Address that pointed to the module to be removed in the linked list\\n /// @param module Module to be removed.\\n function disableModule(address prevModule, address module) external;\\n\\n /// @dev Allows a Module to execute a transaction.\\n /// @notice Can only be called by an enabled module.\\n /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.\\n /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.\\n /// @param to Destination address of module transaction.\\n /// @param value Ether value of module transaction.\\n /// @param data Data payload of module transaction.\\n /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.\\n function execTransactionFromModule(\\n address to,\\n uint256 value,\\n bytes memory data,\\n Enum.Operation operation\\n ) external returns (bool success);\\n\\n /// @dev Allows a Module to execute a transaction and return data\\n /// @notice Can only be called by an enabled module.\\n /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.\\n /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.\\n /// @param to Destination address of module transaction.\\n /// @param value Ether value of module transaction.\\n /// @param data Data payload of module transaction.\\n /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.\\n function execTransactionFromModuleReturnData(\\n address to,\\n uint256 value,\\n bytes memory data,\\n Enum.Operation operation\\n ) external returns (bool success, bytes memory returnData);\\n\\n /// @dev Returns if an module is enabled\\n /// @return True if the module is enabled\\n function isModuleEnabled(address module) external view returns (bool);\\n\\n /// @dev Returns array of modules.\\n /// @param start Start of the page.\\n /// @param pageSize Maximum number of modules that should be returned.\\n /// @return array Array of modules.\\n /// @return next Start of the next page.\\n function getModulesPaginated(address start, uint256 pageSize)\\n external\\n view\\n returns (address[] memory array, address next);\\n}\\n\",\"keccak256\":\"0xcd5508ffe596eef8fbccfd5fc4f10a34397773547ce64e212d48b5212865ec1f\",\"license\":\"LGPL-3.0-only\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n}\\n\",\"keccak256\":\"0xaf159a8b1923ad2a26d516089bceca9bdeaeacd04be50983ea00ba63070f08a3\",\"license\":\"MIT\"},\"contracts/DecentHats_0_1_0.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity =0.8.19;\\n\\nimport {Enum} from \\\"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\\\";\\nimport {IAvatar} from \\\"@gnosis.pm/zodiac/contracts/interfaces/IAvatar.sol\\\";\\nimport {Strings} from \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport {IERC6551Registry} from \\\"./interfaces/IERC6551Registry.sol\\\";\\nimport {IHats} from \\\"./interfaces/hats/IHats.sol\\\";\\nimport {ISablierV2LockupLinear} from \\\"./interfaces/sablier/ISablierV2LockupLinear.sol\\\";\\nimport {LockupLinear} from \\\"./interfaces/sablier/LockupLinear.sol\\\";\\n\\ncontract DecentHats_0_1_0 {\\n string public constant NAME = \\\"DecentHats_0_1_0\\\";\\n\\n struct SablierStreamParams {\\n ISablierV2LockupLinear sablier;\\n address sender;\\n uint128 totalAmount;\\n address asset;\\n bool cancelable;\\n bool transferable;\\n LockupLinear.Timestamps timestamps;\\n LockupLinear.Broker broker;\\n }\\n\\n struct Hat {\\n uint32 maxSupply;\\n string details;\\n string imageURI;\\n bool isMutable;\\n address wearer;\\n SablierStreamParams[] sablierParams; // Optional Sablier stream parameters\\n }\\n\\n struct CreateTreeParams {\\n IHats hatsProtocol;\\n address hatsAccountImplementation;\\n IERC6551Registry registry;\\n address keyValuePairs;\\n string topHatDetails;\\n string topHatImageURI;\\n Hat adminHat;\\n Hat[] hats;\\n }\\n\\n function getSalt() internal view returns (bytes32 salt) {\\n uint256 chainId;\\n assembly {\\n chainId := chainid()\\n }\\n\\n bytes memory concatenatedSaltInput = abi.encodePacked(\\n NAME,\\n chainId,\\n address(this)\\n );\\n\\n salt = keccak256(concatenatedSaltInput);\\n }\\n\\n function updateKeyValuePairs(\\n address _keyValuePairs,\\n uint256 topHatId\\n ) internal {\\n string[] memory keys = new string[](1);\\n string[] memory values = new string[](1);\\n keys[0] = \\\"topHatId\\\";\\n values[0] = Strings.toString(topHatId);\\n\\n IAvatar(msg.sender).execTransactionFromModule(\\n _keyValuePairs,\\n 0,\\n abi.encodeWithSignature(\\n \\\"updateValues(string[],string[])\\\",\\n keys,\\n values\\n ),\\n Enum.Operation.Call\\n );\\n }\\n\\n function createHat(\\n IHats _hatsProtocol,\\n uint256 adminHatId,\\n Hat memory _hat,\\n address topHatAccount\\n ) internal returns (uint256) {\\n return\\n _hatsProtocol.createHat(\\n adminHatId,\\n _hat.details,\\n _hat.maxSupply,\\n topHatAccount,\\n topHatAccount,\\n _hat.isMutable,\\n _hat.imageURI\\n );\\n }\\n\\n function createAccount(\\n IERC6551Registry _registry,\\n address _hatsAccountImplementation,\\n bytes32 salt,\\n address protocolAddress,\\n uint256 hatId\\n ) internal returns (address) {\\n return\\n _registry.createAccount(\\n _hatsAccountImplementation,\\n salt,\\n block.chainid,\\n protocolAddress,\\n hatId\\n );\\n }\\n\\n function createTopHatAndAccount(\\n IHats _hatsProtocol,\\n string memory _topHatDetails,\\n string memory _topHatImageURI,\\n IERC6551Registry _registry,\\n address _hatsAccountImplementation,\\n bytes32 salt\\n ) internal returns (uint256 topHatId, address topHatAccount) {\\n topHatId = _hatsProtocol.mintTopHat(\\n address(this),\\n _topHatDetails,\\n _topHatImageURI\\n );\\n\\n topHatAccount = createAccount(\\n _registry,\\n _hatsAccountImplementation,\\n salt,\\n address(_hatsProtocol),\\n topHatId\\n );\\n }\\n\\n function createHatAndAccountAndMintAndStreams(\\n IHats hatsProtocol,\\n uint256 adminHatId,\\n Hat calldata hat,\\n address topHatAccount,\\n IERC6551Registry registry,\\n address hatsAccountImplementation,\\n bytes32 salt\\n ) internal returns (uint256 hatId, address accountAddress) {\\n hatId = createHat(hatsProtocol, adminHatId, hat, topHatAccount);\\n\\n accountAddress = createAccount(\\n registry,\\n hatsAccountImplementation,\\n salt,\\n address(hatsProtocol),\\n hatId\\n );\\n\\n if (hat.wearer != address(0)) {\\n hatsProtocol.mintHat(hatId, hat.wearer);\\n }\\n\\n for (uint256 i = 0; i < hat.sablierParams.length; ) {\\n SablierStreamParams memory sablierParams = hat.sablierParams[i];\\n\\n // Approve tokens for Sablier\\n IAvatar(msg.sender).execTransactionFromModule(\\n sablierParams.asset,\\n 0,\\n abi.encodeWithSignature(\\n \\\"approve(address,uint256)\\\",\\n address(sablierParams.sablier),\\n sablierParams.totalAmount\\n ),\\n Enum.Operation.Call\\n );\\n\\n LockupLinear.CreateWithTimestamps memory params = LockupLinear\\n .CreateWithTimestamps({\\n sender: sablierParams.sender,\\n recipient: accountAddress,\\n totalAmount: sablierParams.totalAmount,\\n asset: IERC20(sablierParams.asset),\\n cancelable: sablierParams.cancelable,\\n transferable: sablierParams.transferable,\\n timestamps: sablierParams.timestamps,\\n broker: sablierParams.broker\\n });\\n\\n // Proxy the Sablier call through IAvatar\\n IAvatar(msg.sender).execTransactionFromModule(\\n address(sablierParams.sablier),\\n 0,\\n abi.encodeWithSignature(\\n \\\"createWithTimestamps((address,address,uint128,address,bool,bool,(uint40,uint40,uint40),(address,uint256)))\\\",\\n params\\n ),\\n Enum.Operation.Call\\n );\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n function createAndDeclareTree(CreateTreeParams calldata params) public {\\n bytes32 salt = getSalt();\\n\\n (uint256 topHatId, address topHatAccount) = createTopHatAndAccount(\\n params.hatsProtocol,\\n params.topHatDetails,\\n params.topHatImageURI,\\n params.registry,\\n params.hatsAccountImplementation,\\n salt\\n );\\n\\n updateKeyValuePairs(params.keyValuePairs, topHatId);\\n\\n (uint256 adminHatId, ) = createHatAndAccountAndMintAndStreams(\\n params.hatsProtocol,\\n topHatId,\\n params.adminHat,\\n topHatAccount,\\n params.registry,\\n params.hatsAccountImplementation,\\n salt\\n );\\n\\n for (uint256 i = 0; i < params.hats.length; ) {\\n createHatAndAccountAndMintAndStreams(\\n params.hatsProtocol,\\n adminHatId,\\n params.hats[i],\\n topHatAccount,\\n params.registry,\\n params.hatsAccountImplementation,\\n salt\\n );\\n\\n unchecked {\\n ++i;\\n }\\n }\\n\\n params.hatsProtocol.transferHat(topHatId, address(this), msg.sender);\\n }\\n}\\n\",\"keccak256\":\"0xdc0d2b3c556d675f26152895a17e1fb76c91d1a85b2689cf435fb3666381ac41\",\"license\":\"MIT\"},\"contracts/interfaces/IERC6551Registry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.4;\\n\\ninterface IERC6551Registry {\\n /**\\n * @dev Creates a token bound account for a non-fungible token.\\n *\\n * If account has already been created, returns the account address without calling create2.\\n *\\n * Emits ERC6551AccountCreated event.\\n *\\n * @return account The address of the token bound account\\n */\\n function createAccount(\\n address implementation,\\n bytes32 salt,\\n uint256 chainId,\\n address tokenContract,\\n uint256 tokenId\\n ) external returns (address account);\\n}\\n\",\"keccak256\":\"0x64c52de8a8e68398e61dd8b42dda8e9af8cf6abf93bb85629c322440991ea568\",\"license\":\"MIT\"},\"contracts/interfaces/hats/IHats.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0\\n// Copyright (C) 2023 Haberdasher Labs\\n//\\n// This program is free software: you can redistribute it and/or modify\\n// it under the terms of the GNU Affero General Public License as published by\\n// the Free Software Foundation, either version 3 of the License, or\\n// (at your option) any later version.\\n//\\n// This program is distributed in the hope that it will be useful,\\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\\n// GNU Affero General Public License for more details.\\n//\\n// You should have received a copy of the GNU Affero General Public License\\n// along with this program. If not, see .\\n\\npragma solidity >=0.8.13;\\n\\ninterface IHats {\\n function mintTopHat(\\n address _target,\\n string memory _details,\\n string memory _imageURI\\n ) external returns (uint256 topHatId);\\n\\n function createHat(\\n uint256 _admin,\\n string calldata _details,\\n uint32 _maxSupply,\\n address _eligibility,\\n address _toggle,\\n bool _mutable,\\n string calldata _imageURI\\n ) external returns (uint256 newHatId);\\n\\n function mintHat(\\n uint256 _hatId,\\n address _wearer\\n ) external returns (bool success);\\n\\n function transferHat(uint256 _hatId, address _from, address _to) external;\\n}\\n\",\"keccak256\":\"0x8e35022f5c0fcf0059033abec78ec890f0cf3bbac09d6d24051cff9679239511\",\"license\":\"AGPL-3.0\"},\"contracts/interfaces/sablier/ISablierV2LockupLinear.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {LockupLinear} from \\\"./LockupLinear.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface ISablierV2LockupLinear {\\n function createWithTimestamps(\\n LockupLinear.CreateWithTimestamps calldata params\\n ) external returns (uint256 streamId);\\n}\\n\",\"keccak256\":\"0xf4899637eb2e6c76c35e2d201e56e162a50e6bc7b5b9156e00866f0703ad07ca\",\"license\":\"MIT\"},\"contracts/interfaces/sablier/LockupLinear.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nlibrary LockupLinear {\\n struct CreateWithTimestamps {\\n address sender;\\n address recipient;\\n uint128 totalAmount;\\n IERC20 asset;\\n bool cancelable;\\n bool transferable;\\n Timestamps timestamps;\\n Broker broker;\\n }\\n\\n struct Timestamps {\\n uint40 start;\\n uint40 cliff;\\n uint40 end;\\n }\\n\\n struct Broker {\\n address account;\\n uint256 fee;\\n }\\n}\\n\",\"keccak256\":\"0x497fdb52b5e1a5a7e0711a9f7d5fb036eb668ccb92ea908ee088f56ee08a4ce8\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50611477806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80638c5f591a1461003b578063a3f4df7e14610050575b600080fd5b61004e610049366004610ac2565b610095565b005b61007f6040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b81525081565b60405161008c9190610b54565b60405180910390f35b600061009f6102cd565b905060008061015e6100b46020860186610b7f565b6100c16080870187610b9c565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506101039250505060a0880188610b9c565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610148925050506060890160408a01610b7f565b61015860408a0160208b01610b7f565b88610331565b909250905061017c6101766080860160608701610b7f565b836103c3565b60006101c361018e6020870187610b7f565b8461019c60c0890189610bf9565b856101ad60608b0160408c01610b7f565b6101bd60408c0160208d01610b7f565b8a610543565b50905060005b6101d660e0870187610c19565b9050811015610250576102466101ef6020880188610b7f565b836101fd60e08a018a610c19565b8581811061020d5761020d610c62565b905060200281019061021f9190610bf9565b8661023060608c0160408d01610b7f565b61024060408d0160208e01610b7f565b8b610543565b50506001016101c9565b5061025e6020860186610b7f565b6040516329287c1b60e21b8152600481018590523060248201523360448201526001600160a01b03919091169063a4a1f06c90606401600060405180830381600087803b1580156102ae57600080fd5b505af11580156102c2573d6000803e3d6000fd5b505050505050505050565b60008046905060006040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b815250823060405160200161031293929190610c78565b60408051601f1981840301815291905280516020909101209392505050565b600080876001600160a01b0316631a64dfad3089896040518463ffffffff1660e01b815260040161036493929190610cb1565b6020604051808303816000875af1158015610383573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a79190610ce7565b91506103b68585858b86610892565b9050965096945050505050565b604080516001808252818301909252600091816020015b60608152602001906001900390816103da57505060408051600180825281830190925291925060009190602082015b6060815260200190600190039081610409579050509050604051806040016040528060088152602001671d1bdc12185d125960c21b8152508260008151811061045457610454610c62565b602002602001018190525061046883610928565b8160008151811061047b5761047b610c62565b6020026020010181905250336001600160a01b031663468721a785600085856040516024016104ab929190610d6b565b60408051601f198184030181529181526020820180516001600160e01b031663579374b960e11b1790525160e085901b6001600160e01b03191681526104f993929190600090600401610d90565b6020604051808303816000875af1158015610518573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053c9190610df4565b5050505050565b60008061055a89896105548a61113b565b89610a30565b91506105698585858c86610892565b9050600061057d60a0890160808a01610b7f565b6001600160a01b03161461061d576001600160a01b03891663641f776e836105ab60a08b0160808c01610b7f565b6040516001600160e01b031960e085901b16815260048101929092526001600160a01b031660248201526044016020604051808303816000875af11580156105f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061b9190610df4565b505b60005b61062d60a08901896111ff565b905081101561088557600061064560a08a018a6111ff565b8381811061065557610655610c62565b9050610160020180360381019061066c9190611248565b6060810151815160408084015190516001600160a01b0390921660248301526001600160801b03166044820152919250339163468721a7919060009060640160408051601f198184030181529181526020820180516001600160e01b031663095ea7b360e01b1790525160e085901b6001600160e01b03191681526106f993929190600090600401610d90565b6020604051808303816000875af1158015610718573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073c9190610df4565b50600060405180610100016040528083602001516001600160a01b03168152602001856001600160a01b0316815260200183604001516001600160801b0316815260200183606001516001600160a01b031681526020018360800151151581526020018360a00151151581526020018360c0015181526020018360e001518152509050336001600160a01b031663468721a783600001516000846040516024016107e69190611265565b60408051601f198184030181529181526020820180516001600160e01b03166353b1572760e01b1790525160e085901b6001600160e01b031916815261083493929190600090600401610d90565b6020604051808303816000875af1158015610853573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108779190610df4565b508260010192505050610620565b5097509795505050505050565b604051638a54c52f60e01b81526001600160a01b0385811660048301526024820185905246604483015283811660648301526084820183905260009190871690638a54c52f9060a4016020604051808303816000875af11580156108fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091e9190611327565b9695505050505050565b60608160000361094f5750506040805180820190915260018152600360fc1b602082015290565b8160005b811561097957806109638161135a565b91506109729050600a83611389565b9150610953565b6000816001600160401b0381111561099357610993610d00565b6040519080825280601f01601f1916602001820160405280156109bd576020820181803683370190505b5090505b8415610a28576109d260018361139d565b91506109df600a866113b6565b6109ea9060306113ca565b60f81b8183815181106109ff576109ff610c62565b60200101906001600160f81b031916908160001a905350610a21600a86611389565b94506109c1565b949350505050565b6020820151825160608401516040808601519051635829492f60e11b81526000946001600160a01b038a169463b052925e94610a76948b948a92839290916004016113dd565b6020604051808303816000875af1158015610a95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab99190610ce7565b95945050505050565b600060208284031215610ad457600080fd5b81356001600160401b03811115610aea57600080fd5b82016101008185031215610afd57600080fd5b9392505050565b60005b83811015610b1f578181015183820152602001610b07565b50506000910152565b60008151808452610b40816020860160208601610b04565b601f01601f19169290920160200192915050565b602081526000610afd6020830184610b28565b6001600160a01b0381168114610b7c57600080fd5b50565b600060208284031215610b9157600080fd5b8135610afd81610b67565b6000808335601e19843603018112610bb357600080fd5b8301803591506001600160401b03821115610bcd57600080fd5b602001915036819003821315610be257600080fd5b9250929050565b8035610bf481610b67565b919050565b6000823560be19833603018112610c0f57600080fd5b9190910192915050565b6000808335601e19843603018112610c3057600080fd5b8301803591506001600160401b03821115610c4a57600080fd5b6020019150600581901b3603821315610be257600080fd5b634e487b7160e01b600052603260045260246000fd5b60008451610c8a818460208901610b04565b919091019283525060601b6bffffffffffffffffffffffff19166020820152603401919050565b6001600160a01b0384168152606060208201819052600090610cd590830185610b28565b828103604084015261091e8185610b28565b600060208284031215610cf957600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b600081518084526020808501808196508360051b8101915082860160005b85811015610d5e578284038952610d4c848351610b28565b98850198935090840190600101610d34565b5091979650505050505050565b604081526000610d7e6040830185610d16565b8281036020840152610ab98185610d16565b60018060a01b0385168152836020820152608060408201526000610db76080830185610b28565b905060028310610dd757634e487b7160e01b600052602160045260246000fd5b82606083015295945050505050565b8015158114610b7c57600080fd5b600060208284031215610e0657600080fd5b8151610afd81610de6565b60405160c081016001600160401b0381118282101715610e3357610e33610d00565b60405290565b604051601f8201601f191681016001600160401b0381118282101715610e6157610e61610d00565b604052919050565b803563ffffffff81168114610bf457600080fd5b600082601f830112610e8e57600080fd5b81356001600160401b03811115610ea757610ea7610d00565b610eba601f8201601f1916602001610e39565b818152846020838601011115610ecf57600080fd5b816020850160208301376000918101602001919091529392505050565b8035610bf481610de6565b80356001600160801b0381168114610bf457600080fd5b803564ffffffffff81168114610bf457600080fd5b600060608284031215610f3557600080fd5b604051606081018181106001600160401b0382111715610f5757610f57610d00565b604052905080610f6683610f0e565b8152610f7460208401610f0e565b6020820152610f8560408401610f0e565b60408201525092915050565b600060408284031215610fa357600080fd5b604051604081018181106001600160401b0382111715610fc557610fc5610d00565b6040529050808235610fd681610b67565b8152602092830135920191909152919050565b60006101608284031215610ffc57600080fd5b60405161010081018181106001600160401b038211171561101f5761101f610d00565b60405290508061102e83610be9565b815261103c60208401610be9565b602082015261104d60408401610ef7565b604082015261105e60608401610be9565b606082015261106f60808401610eec565b608082015261108060a08401610eec565b60a08201526110928460c08501610f23565b60c08201526110a5846101208501610f91565b60e08201525092915050565b600082601f8301126110c257600080fd5b813560206001600160401b038211156110dd576110dd610d00565b6110eb818360051b01610e39565b828152610160928302850182019282820191908785111561110b57600080fd5b8387015b8581101561112e576111218982610fe9565b845292840192810161110f565b5090979650505050505050565b600060c0823603121561114d57600080fd5b611155610e11565b61115e83610e69565b815260208301356001600160401b038082111561117a57600080fd5b61118636838701610e7d565b6020840152604085013591508082111561119f57600080fd5b6111ab36838701610e7d565b60408401526111bc60608601610eec565b60608401526111cd60808601610be9565b608084015260a08501359150808211156111e657600080fd5b506111f3368286016110b1565b60a08301525092915050565b6000808335601e1984360301811261121657600080fd5b8301803591506001600160401b0382111561123057600080fd5b602001915061016081023603821315610be257600080fd5b6000610160828403121561125b57600080fd5b610afd8383610fe9565b81516001600160a01b0390811682526020808401518216908301526040808401516001600160801b031690830152606080840151909116908201526080808301516101608301916112b99084018215159052565b5060a08301516112cd60a084018215159052565b5060c083015161130060c0840182805164ffffffffff908116835260208083015182169084015260409182015116910152565b5060e0929092015180516001600160a01b0316610120830152602001516101409091015290565b60006020828403121561133957600080fd5b8151610afd81610b67565b634e487b7160e01b600052601160045260246000fd5b60006001820161136c5761136c611344565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261139857611398611373565b500490565b818103818111156113b0576113b0611344565b92915050565b6000826113c5576113c5611373565b500690565b808201808211156113b0576113b0611344565b87815260e0602082015260006113f660e0830189610b28565b63ffffffff881660408401526001600160a01b0387811660608501528616608084015284151560a084015282810360c08401526114338185610b28565b9a995050505050505050505056fea2646970667358221220d17954ba81bca52da6ca1f1cf74a0e04f2ce3c50651d1d806611eb18ab0d551e64736f6c63430008130033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80638c5f591a1461003b578063a3f4df7e14610050575b600080fd5b61004e610049366004610ac2565b610095565b005b61007f6040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b81525081565b60405161008c9190610b54565b60405180910390f35b600061009f6102cd565b905060008061015e6100b46020860186610b7f565b6100c16080870187610b9c565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506101039250505060a0880188610b9c565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610148925050506060890160408a01610b7f565b61015860408a0160208b01610b7f565b88610331565b909250905061017c6101766080860160608701610b7f565b836103c3565b60006101c361018e6020870187610b7f565b8461019c60c0890189610bf9565b856101ad60608b0160408c01610b7f565b6101bd60408c0160208d01610b7f565b8a610543565b50905060005b6101d660e0870187610c19565b9050811015610250576102466101ef6020880188610b7f565b836101fd60e08a018a610c19565b8581811061020d5761020d610c62565b905060200281019061021f9190610bf9565b8661023060608c0160408d01610b7f565b61024060408d0160208e01610b7f565b8b610543565b50506001016101c9565b5061025e6020860186610b7f565b6040516329287c1b60e21b8152600481018590523060248201523360448201526001600160a01b03919091169063a4a1f06c90606401600060405180830381600087803b1580156102ae57600080fd5b505af11580156102c2573d6000803e3d6000fd5b505050505050505050565b60008046905060006040518060400160405280601081526020016f0446563656e74486174735f305f315f360841b815250823060405160200161031293929190610c78565b60408051601f1981840301815291905280516020909101209392505050565b600080876001600160a01b0316631a64dfad3089896040518463ffffffff1660e01b815260040161036493929190610cb1565b6020604051808303816000875af1158015610383573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a79190610ce7565b91506103b68585858b86610892565b9050965096945050505050565b604080516001808252818301909252600091816020015b60608152602001906001900390816103da57505060408051600180825281830190925291925060009190602082015b6060815260200190600190039081610409579050509050604051806040016040528060088152602001671d1bdc12185d125960c21b8152508260008151811061045457610454610c62565b602002602001018190525061046883610928565b8160008151811061047b5761047b610c62565b6020026020010181905250336001600160a01b031663468721a785600085856040516024016104ab929190610d6b565b60408051601f198184030181529181526020820180516001600160e01b031663579374b960e11b1790525160e085901b6001600160e01b03191681526104f993929190600090600401610d90565b6020604051808303816000875af1158015610518573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053c9190610df4565b5050505050565b60008061055a89896105548a61113b565b89610a30565b91506105698585858c86610892565b9050600061057d60a0890160808a01610b7f565b6001600160a01b03161461061d576001600160a01b03891663641f776e836105ab60a08b0160808c01610b7f565b6040516001600160e01b031960e085901b16815260048101929092526001600160a01b031660248201526044016020604051808303816000875af11580156105f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061b9190610df4565b505b60005b61062d60a08901896111ff565b905081101561088557600061064560a08a018a6111ff565b8381811061065557610655610c62565b9050610160020180360381019061066c9190611248565b6060810151815160408084015190516001600160a01b0390921660248301526001600160801b03166044820152919250339163468721a7919060009060640160408051601f198184030181529181526020820180516001600160e01b031663095ea7b360e01b1790525160e085901b6001600160e01b03191681526106f993929190600090600401610d90565b6020604051808303816000875af1158015610718573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073c9190610df4565b50600060405180610100016040528083602001516001600160a01b03168152602001856001600160a01b0316815260200183604001516001600160801b0316815260200183606001516001600160a01b031681526020018360800151151581526020018360a00151151581526020018360c0015181526020018360e001518152509050336001600160a01b031663468721a783600001516000846040516024016107e69190611265565b60408051601f198184030181529181526020820180516001600160e01b03166353b1572760e01b1790525160e085901b6001600160e01b031916815261083493929190600090600401610d90565b6020604051808303816000875af1158015610853573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108779190610df4565b508260010192505050610620565b5097509795505050505050565b604051638a54c52f60e01b81526001600160a01b0385811660048301526024820185905246604483015283811660648301526084820183905260009190871690638a54c52f9060a4016020604051808303816000875af11580156108fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061091e9190611327565b9695505050505050565b60608160000361094f5750506040805180820190915260018152600360fc1b602082015290565b8160005b811561097957806109638161135a565b91506109729050600a83611389565b9150610953565b6000816001600160401b0381111561099357610993610d00565b6040519080825280601f01601f1916602001820160405280156109bd576020820181803683370190505b5090505b8415610a28576109d260018361139d565b91506109df600a866113b6565b6109ea9060306113ca565b60f81b8183815181106109ff576109ff610c62565b60200101906001600160f81b031916908160001a905350610a21600a86611389565b94506109c1565b949350505050565b6020820151825160608401516040808601519051635829492f60e11b81526000946001600160a01b038a169463b052925e94610a76948b948a92839290916004016113dd565b6020604051808303816000875af1158015610a95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab99190610ce7565b95945050505050565b600060208284031215610ad457600080fd5b81356001600160401b03811115610aea57600080fd5b82016101008185031215610afd57600080fd5b9392505050565b60005b83811015610b1f578181015183820152602001610b07565b50506000910152565b60008151808452610b40816020860160208601610b04565b601f01601f19169290920160200192915050565b602081526000610afd6020830184610b28565b6001600160a01b0381168114610b7c57600080fd5b50565b600060208284031215610b9157600080fd5b8135610afd81610b67565b6000808335601e19843603018112610bb357600080fd5b8301803591506001600160401b03821115610bcd57600080fd5b602001915036819003821315610be257600080fd5b9250929050565b8035610bf481610b67565b919050565b6000823560be19833603018112610c0f57600080fd5b9190910192915050565b6000808335601e19843603018112610c3057600080fd5b8301803591506001600160401b03821115610c4a57600080fd5b6020019150600581901b3603821315610be257600080fd5b634e487b7160e01b600052603260045260246000fd5b60008451610c8a818460208901610b04565b919091019283525060601b6bffffffffffffffffffffffff19166020820152603401919050565b6001600160a01b0384168152606060208201819052600090610cd590830185610b28565b828103604084015261091e8185610b28565b600060208284031215610cf957600080fd5b5051919050565b634e487b7160e01b600052604160045260246000fd5b600081518084526020808501808196508360051b8101915082860160005b85811015610d5e578284038952610d4c848351610b28565b98850198935090840190600101610d34565b5091979650505050505050565b604081526000610d7e6040830185610d16565b8281036020840152610ab98185610d16565b60018060a01b0385168152836020820152608060408201526000610db76080830185610b28565b905060028310610dd757634e487b7160e01b600052602160045260246000fd5b82606083015295945050505050565b8015158114610b7c57600080fd5b600060208284031215610e0657600080fd5b8151610afd81610de6565b60405160c081016001600160401b0381118282101715610e3357610e33610d00565b60405290565b604051601f8201601f191681016001600160401b0381118282101715610e6157610e61610d00565b604052919050565b803563ffffffff81168114610bf457600080fd5b600082601f830112610e8e57600080fd5b81356001600160401b03811115610ea757610ea7610d00565b610eba601f8201601f1916602001610e39565b818152846020838601011115610ecf57600080fd5b816020850160208301376000918101602001919091529392505050565b8035610bf481610de6565b80356001600160801b0381168114610bf457600080fd5b803564ffffffffff81168114610bf457600080fd5b600060608284031215610f3557600080fd5b604051606081018181106001600160401b0382111715610f5757610f57610d00565b604052905080610f6683610f0e565b8152610f7460208401610f0e565b6020820152610f8560408401610f0e565b60408201525092915050565b600060408284031215610fa357600080fd5b604051604081018181106001600160401b0382111715610fc557610fc5610d00565b6040529050808235610fd681610b67565b8152602092830135920191909152919050565b60006101608284031215610ffc57600080fd5b60405161010081018181106001600160401b038211171561101f5761101f610d00565b60405290508061102e83610be9565b815261103c60208401610be9565b602082015261104d60408401610ef7565b604082015261105e60608401610be9565b606082015261106f60808401610eec565b608082015261108060a08401610eec565b60a08201526110928460c08501610f23565b60c08201526110a5846101208501610f91565b60e08201525092915050565b600082601f8301126110c257600080fd5b813560206001600160401b038211156110dd576110dd610d00565b6110eb818360051b01610e39565b828152610160928302850182019282820191908785111561110b57600080fd5b8387015b8581101561112e576111218982610fe9565b845292840192810161110f565b5090979650505050505050565b600060c0823603121561114d57600080fd5b611155610e11565b61115e83610e69565b815260208301356001600160401b038082111561117a57600080fd5b61118636838701610e7d565b6020840152604085013591508082111561119f57600080fd5b6111ab36838701610e7d565b60408401526111bc60608601610eec565b60608401526111cd60808601610be9565b608084015260a08501359150808211156111e657600080fd5b506111f3368286016110b1565b60a08301525092915050565b6000808335601e1984360301811261121657600080fd5b8301803591506001600160401b0382111561123057600080fd5b602001915061016081023603821315610be257600080fd5b6000610160828403121561125b57600080fd5b610afd8383610fe9565b81516001600160a01b0390811682526020808401518216908301526040808401516001600160801b031690830152606080840151909116908201526080808301516101608301916112b99084018215159052565b5060a08301516112cd60a084018215159052565b5060c083015161130060c0840182805164ffffffffff908116835260208083015182169084015260409182015116910152565b5060e0929092015180516001600160a01b0316610120830152602001516101409091015290565b60006020828403121561133957600080fd5b8151610afd81610b67565b634e487b7160e01b600052601160045260246000fd5b60006001820161136c5761136c611344565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261139857611398611373565b500490565b818103818111156113b0576113b0611344565b92915050565b6000826113c5576113c5611373565b500690565b808201808211156113b0576113b0611344565b87815260e0602082015260006113f660e0830189610b28565b63ffffffff881660408401526001600160a01b0387811660608501528616608084015284151560a084015282810360c08401526114338185610b28565b9a995050505050505050505056fea2646970667358221220d17954ba81bca52da6ca1f1cf74a0e04f2ce3c50651d1d806611eb18ab0d551e64736f6c63430008130033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/sepolia/solcInputs/512807b5d71481c693c202ae23158904.json b/deployments/sepolia/solcInputs/512807b5d71481c693c202ae23158904.json new file mode 100644 index 00000000..0d0d55c8 --- /dev/null +++ b/deployments/sepolia/solcInputs/512807b5d71481c693c202ae23158904.json @@ -0,0 +1,59 @@ +{ + "language": "Solidity", + "sources": { + "@gnosis.pm/safe-contracts/contracts/common/Enum.sol": { + "content": "// SPDX-License-Identifier: LGPL-3.0-only\npragma solidity >=0.7.0 <0.9.0;\n\n/// @title Enum - Collection of enums\n/// @author Richard Meissner - \ncontract Enum {\n enum Operation {Call, DelegateCall}\n}\n" + }, + "@gnosis.pm/zodiac/contracts/interfaces/IAvatar.sol": { + "content": "// SPDX-License-Identifier: LGPL-3.0-only\n\n/// @title Zodiac Avatar - A contract that manages modules that can execute transactions via this contract.\npragma solidity >=0.7.0 <0.9.0;\n\nimport \"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\";\n\ninterface IAvatar {\n event EnabledModule(address module);\n event DisabledModule(address module);\n event ExecutionFromModuleSuccess(address indexed module);\n event ExecutionFromModuleFailure(address indexed module);\n\n /// @dev Enables a module on the avatar.\n /// @notice Can only be called by the avatar.\n /// @notice Modules should be stored as a linked list.\n /// @notice Must emit EnabledModule(address module) if successful.\n /// @param module Module to be enabled.\n function enableModule(address module) external;\n\n /// @dev Disables a module on the avatar.\n /// @notice Can only be called by the avatar.\n /// @notice Must emit DisabledModule(address module) if successful.\n /// @param prevModule Address that pointed to the module to be removed in the linked list\n /// @param module Module to be removed.\n function disableModule(address prevModule, address module) external;\n\n /// @dev Allows a Module to execute a transaction.\n /// @notice Can only be called by an enabled module.\n /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.\n /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.\n /// @param to Destination address of module transaction.\n /// @param value Ether value of module transaction.\n /// @param data Data payload of module transaction.\n /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.\n function execTransactionFromModule(\n address to,\n uint256 value,\n bytes memory data,\n Enum.Operation operation\n ) external returns (bool success);\n\n /// @dev Allows a Module to execute a transaction and return data\n /// @notice Can only be called by an enabled module.\n /// @notice Must emit ExecutionFromModuleSuccess(address module) if successful.\n /// @notice Must emit ExecutionFromModuleFailure(address module) if unsuccessful.\n /// @param to Destination address of module transaction.\n /// @param value Ether value of module transaction.\n /// @param data Data payload of module transaction.\n /// @param operation Operation type of module transaction: 0 == call, 1 == delegate call.\n function execTransactionFromModuleReturnData(\n address to,\n uint256 value,\n bytes memory data,\n Enum.Operation operation\n ) external returns (bool success, bytes memory returnData);\n\n /// @dev Returns if an module is enabled\n /// @return True if the module is enabled\n function isModuleEnabled(address module) external view returns (bool);\n\n /// @dev Returns array of modules.\n /// @param start Start of the page.\n /// @param pageSize Maximum number of modules that should be returned.\n /// @return array Array of modules.\n /// @return next Start of the next page.\n function getModulesPaginated(address start, uint256 pageSize)\n external\n view\n returns (address[] memory array, address next);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp >>= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n" + }, + "contracts/DecentHats_0_1_0.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity =0.8.19;\n\nimport {Enum} from \"@gnosis.pm/safe-contracts/contracts/common/Enum.sol\";\nimport {IAvatar} from \"@gnosis.pm/zodiac/contracts/interfaces/IAvatar.sol\";\nimport {Strings} from \"@openzeppelin/contracts/utils/Strings.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {IERC6551Registry} from \"./interfaces/IERC6551Registry.sol\";\nimport {IHats} from \"./interfaces/hats/IHats.sol\";\nimport {ISablierV2LockupLinear} from \"./interfaces/sablier/ISablierV2LockupLinear.sol\";\nimport {LockupLinear} from \"./interfaces/sablier/LockupLinear.sol\";\n\ncontract DecentHats_0_1_0 {\n string public constant NAME = \"DecentHats_0_1_0\";\n\n struct SablierStreamParams {\n ISablierV2LockupLinear sablier;\n address sender;\n uint128 totalAmount;\n address asset;\n bool cancelable;\n bool transferable;\n LockupLinear.Timestamps timestamps;\n LockupLinear.Broker broker;\n }\n\n struct Hat {\n uint32 maxSupply;\n string details;\n string imageURI;\n bool isMutable;\n address wearer;\n SablierStreamParams[] sablierParams; // Optional Sablier stream parameters\n }\n\n struct CreateTreeParams {\n IHats hatsProtocol;\n address hatsAccountImplementation;\n IERC6551Registry registry;\n address keyValuePairs;\n string topHatDetails;\n string topHatImageURI;\n Hat adminHat;\n Hat[] hats;\n }\n\n function getSalt() internal view returns (bytes32 salt) {\n uint256 chainId;\n assembly {\n chainId := chainid()\n }\n\n bytes memory concatenatedSaltInput = abi.encodePacked(\n NAME,\n chainId,\n address(this)\n );\n\n salt = keccak256(concatenatedSaltInput);\n }\n\n function updateKeyValuePairs(\n address _keyValuePairs,\n uint256 topHatId\n ) internal {\n string[] memory keys = new string[](1);\n string[] memory values = new string[](1);\n keys[0] = \"topHatId\";\n values[0] = Strings.toString(topHatId);\n\n IAvatar(msg.sender).execTransactionFromModule(\n _keyValuePairs,\n 0,\n abi.encodeWithSignature(\n \"updateValues(string[],string[])\",\n keys,\n values\n ),\n Enum.Operation.Call\n );\n }\n\n function createHat(\n IHats _hatsProtocol,\n uint256 adminHatId,\n Hat memory _hat,\n address topHatAccount\n ) internal returns (uint256) {\n return\n _hatsProtocol.createHat(\n adminHatId,\n _hat.details,\n _hat.maxSupply,\n topHatAccount,\n topHatAccount,\n _hat.isMutable,\n _hat.imageURI\n );\n }\n\n function createAccount(\n IERC6551Registry _registry,\n address _hatsAccountImplementation,\n bytes32 salt,\n address protocolAddress,\n uint256 hatId\n ) internal returns (address) {\n return\n _registry.createAccount(\n _hatsAccountImplementation,\n salt,\n block.chainid,\n protocolAddress,\n hatId\n );\n }\n\n function createTopHatAndAccount(\n IHats _hatsProtocol,\n string memory _topHatDetails,\n string memory _topHatImageURI,\n IERC6551Registry _registry,\n address _hatsAccountImplementation,\n bytes32 salt\n ) internal returns (uint256 topHatId, address topHatAccount) {\n topHatId = _hatsProtocol.mintTopHat(\n address(this),\n _topHatDetails,\n _topHatImageURI\n );\n\n topHatAccount = createAccount(\n _registry,\n _hatsAccountImplementation,\n salt,\n address(_hatsProtocol),\n topHatId\n );\n }\n\n function createHatAndAccountAndMintAndStreams(\n IHats hatsProtocol,\n uint256 adminHatId,\n Hat calldata hat,\n address topHatAccount,\n IERC6551Registry registry,\n address hatsAccountImplementation,\n bytes32 salt\n ) internal returns (uint256 hatId, address accountAddress) {\n hatId = createHat(hatsProtocol, adminHatId, hat, topHatAccount);\n\n accountAddress = createAccount(\n registry,\n hatsAccountImplementation,\n salt,\n address(hatsProtocol),\n hatId\n );\n\n if (hat.wearer != address(0)) {\n hatsProtocol.mintHat(hatId, hat.wearer);\n }\n\n for (uint256 i = 0; i < hat.sablierParams.length; ) {\n SablierStreamParams memory sablierParams = hat.sablierParams[i];\n\n // Approve tokens for Sablier\n IAvatar(msg.sender).execTransactionFromModule(\n sablierParams.asset,\n 0,\n abi.encodeWithSignature(\n \"approve(address,uint256)\",\n address(sablierParams.sablier),\n sablierParams.totalAmount\n ),\n Enum.Operation.Call\n );\n\n LockupLinear.CreateWithTimestamps memory params = LockupLinear\n .CreateWithTimestamps({\n sender: sablierParams.sender,\n recipient: accountAddress,\n totalAmount: sablierParams.totalAmount,\n asset: IERC20(sablierParams.asset),\n cancelable: sablierParams.cancelable,\n transferable: sablierParams.transferable,\n timestamps: sablierParams.timestamps,\n broker: sablierParams.broker\n });\n\n // Proxy the Sablier call through IAvatar\n IAvatar(msg.sender).execTransactionFromModule(\n address(sablierParams.sablier),\n 0,\n abi.encodeWithSignature(\n \"createWithTimestamps((address,address,uint128,address,bool,bool,(uint40,uint40,uint40),(address,uint256)))\",\n params\n ),\n Enum.Operation.Call\n );\n\n unchecked {\n ++i;\n }\n }\n }\n\n function createAndDeclareTree(CreateTreeParams calldata params) public {\n bytes32 salt = getSalt();\n\n (uint256 topHatId, address topHatAccount) = createTopHatAndAccount(\n params.hatsProtocol,\n params.topHatDetails,\n params.topHatImageURI,\n params.registry,\n params.hatsAccountImplementation,\n salt\n );\n\n updateKeyValuePairs(params.keyValuePairs, topHatId);\n\n (uint256 adminHatId, ) = createHatAndAccountAndMintAndStreams(\n params.hatsProtocol,\n topHatId,\n params.adminHat,\n topHatAccount,\n params.registry,\n params.hatsAccountImplementation,\n salt\n );\n\n for (uint256 i = 0; i < params.hats.length; ) {\n createHatAndAccountAndMintAndStreams(\n params.hatsProtocol,\n adminHatId,\n params.hats[i],\n topHatAccount,\n params.registry,\n params.hatsAccountImplementation,\n salt\n );\n\n unchecked {\n ++i;\n }\n }\n\n params.hatsProtocol.transferHat(topHatId, address(this), msg.sender);\n }\n}\n" + }, + "contracts/interfaces/hats/IHats.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0\n// Copyright (C) 2023 Haberdasher Labs\n//\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU Affero General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU Affero General Public License for more details.\n//\n// You should have received a copy of the GNU Affero General Public License\n// along with this program. If not, see .\n\npragma solidity >=0.8.13;\n\ninterface IHats {\n function mintTopHat(\n address _target,\n string memory _details,\n string memory _imageURI\n ) external returns (uint256 topHatId);\n\n function createHat(\n uint256 _admin,\n string calldata _details,\n uint32 _maxSupply,\n address _eligibility,\n address _toggle,\n bool _mutable,\n string calldata _imageURI\n ) external returns (uint256 newHatId);\n\n function mintHat(\n uint256 _hatId,\n address _wearer\n ) external returns (bool success);\n\n function transferHat(uint256 _hatId, address _from, address _to) external;\n}\n" + }, + "contracts/interfaces/IERC6551Registry.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\ninterface IERC6551Registry {\n /**\n * @dev Creates a token bound account for a non-fungible token.\n *\n * If account has already been created, returns the account address without calling create2.\n *\n * Emits ERC6551AccountCreated event.\n *\n * @return account The address of the token bound account\n */\n function createAccount(\n address implementation,\n bytes32 salt,\n uint256 chainId,\n address tokenContract,\n uint256 tokenId\n ) external returns (address account);\n}\n" + }, + "contracts/interfaces/sablier/ISablierV2LockupLinear.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {LockupLinear} from \"./LockupLinear.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface ISablierV2LockupLinear {\n function createWithTimestamps(\n LockupLinear.CreateWithTimestamps calldata params\n ) external returns (uint256 streamId);\n}\n" + }, + "contracts/interfaces/sablier/LockupLinear.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nlibrary LockupLinear {\n struct CreateWithTimestamps {\n address sender;\n address recipient;\n uint128 totalAmount;\n IERC20 asset;\n bool cancelable;\n bool transferable;\n Timestamps timestamps;\n Broker broker;\n }\n\n struct Timestamps {\n uint40 start;\n uint40 cliff;\n uint40 end;\n }\n\n struct Broker {\n address account;\n uint256 fee;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/test/DecentHats.test.ts b/test/DecentHats.test.ts deleted file mode 100644 index 1c4ca6fa..00000000 --- a/test/DecentHats.test.ts +++ /dev/null @@ -1,340 +0,0 @@ -/* eslint-disable camelcase */ -import { - GnosisSafeL2, - GnosisSafeL2__factory, - DecentHats_0_1_0__factory, - KeyValuePairs, - KeyValuePairs__factory, - MockHats__factory, - ERC6551Registry__factory, - MockHatsAccount__factory, - ERC6551Registry, - DecentHats_0_1_0, - MockHatsAccount, - MockHats, -} from "../typechain-types"; - -import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; -import { expect } from "chai"; -import { ethers } from "ethers"; -import hre from "hardhat"; - -import { - getGnosisSafeL2Singleton, - getGnosisSafeProxyFactory, -} from "./GlobalSafeDeployments.test"; -import { - buildSafeTransaction, - buildSignatureBytes, - predictGnosisSafeAddress, - safeSignTypedData, -} from "./helpers"; -import { solidityKeccak256 } from "ethers/lib/utils"; - -const executeSafeTransaction = async ({ - safe, - to, - transactionData, - signers, -}: { - safe: GnosisSafeL2; - to: string; - transactionData: string; - signers: SignerWithAddress[]; -}) => { - const safeTx = buildSafeTransaction({ - to, - data: transactionData, - nonce: await safe.nonce(), - }); - - const sigs = await Promise.all( - signers.map(async (signer) => await safeSignTypedData(signer, safe, safeTx)) - ); - - const tx = await safe.execTransaction( - safeTx.to, - safeTx.value, - safeTx.data, - safeTx.operation, - safeTx.safeTxGas, - safeTx.baseGas, - safeTx.gasPrice, - safeTx.gasToken, - safeTx.refundReceiver, - buildSignatureBytes(sigs) - ); - - return tx; -}; - -describe("DecentHats", () => { - let dao: SignerWithAddress; - - let mockHats: MockHats; - let mockHatsAddress: string; - - let keyValuePairs: KeyValuePairs; - let gnosisSafe: GnosisSafeL2; - - let decentHats: DecentHats_0_1_0; - let decentHatsAddress: string; - - let gnosisSafeAddress: string; - let erc6551Registry: ERC6551Registry; - - let mockHatsAccountImplementation: MockHatsAccount; - let mockHatsAccountImplementationAddress: string; - - beforeEach(async () => { - const signers = await hre.ethers.getSigners(); - const [deployer] = signers; - [, dao] = signers; - - mockHats = await new MockHats__factory(deployer).deploy(); - mockHatsAddress = mockHats.address; - keyValuePairs = await new KeyValuePairs__factory(deployer).deploy(); - erc6551Registry = await new ERC6551Registry__factory(deployer).deploy(); - mockHatsAccountImplementation = await new MockHatsAccount__factory( - deployer - ).deploy(); - mockHatsAccountImplementationAddress = - mockHatsAccountImplementation.address; - decentHats = await new DecentHats_0_1_0__factory(deployer).deploy(); - decentHatsAddress = decentHats.address; - - const gnosisSafeProxyFactory = getGnosisSafeProxyFactory(); - const gnosisSafeL2Singleton = getGnosisSafeL2Singleton(); - const gnosisSafeL2SingletonAddress = gnosisSafeL2Singleton.address; - - const createGnosisSetupCalldata = - GnosisSafeL2__factory.createInterface().encodeFunctionData("setup", [ - [dao.address], - 1, - hre.ethers.constants.AddressZero, - hre.ethers.constants.HashZero, - hre.ethers.constants.AddressZero, - hre.ethers.constants.AddressZero, - 0, - hre.ethers.constants.AddressZero, - ]); - - const saltNum = ethers.BigNumber.from( - `0x${Buffer.from(hre.ethers.utils.randomBytes(32)).toString("hex")}` - ); - - const predictedGnosisSafeAddress = await predictGnosisSafeAddress( - createGnosisSetupCalldata, - saltNum, - gnosisSafeL2SingletonAddress, - gnosisSafeProxyFactory - ); - gnosisSafeAddress = predictedGnosisSafeAddress; - - await gnosisSafeProxyFactory.createProxyWithNonce( - gnosisSafeL2SingletonAddress, - createGnosisSetupCalldata, - saltNum - ); - - gnosisSafe = GnosisSafeL2__factory.connect( - predictedGnosisSafeAddress, - deployer - ); - }); - - describe("DecentHats as a Module", () => { - let enableModuleTx: ethers.ContractTransaction; - - beforeEach(async () => { - enableModuleTx = await executeSafeTransaction({ - safe: gnosisSafe, - to: gnosisSafeAddress, - transactionData: - GnosisSafeL2__factory.createInterface().encodeFunctionData( - "enableModule", - [decentHatsAddress] - ), - signers: [dao], - }); - }); - - it("Emits an ExecutionSuccess event", async () => { - await expect(enableModuleTx).to.emit(gnosisSafe, "ExecutionSuccess"); - }); - - it("Emits an EnabledModule event", async () => { - await expect(enableModuleTx) - .to.emit(gnosisSafe, "EnabledModule") - .withArgs(decentHatsAddress); - }); - - describe("Creating a new Top Hat and Tree", () => { - let createAndDeclareTreeTx: ethers.ContractTransaction; - - beforeEach(async () => { - createAndDeclareTreeTx = await executeSafeTransaction({ - safe: gnosisSafe, - to: decentHatsAddress, - transactionData: - DecentHats_0_1_0__factory.createInterface().encodeFunctionData( - "createAndDeclareTree", - [ - { - hatsProtocol: mockHatsAddress, - hatsAccountImplementation: - mockHatsAccountImplementationAddress, - registry: erc6551Registry.address, - keyValuePairs: keyValuePairs.address, - topHatDetails: "", - topHatImageURI: "", - adminHat: { - maxSupply: 1, - details: "", - imageURI: "", - isMutable: false, - wearer: ethers.constants.AddressZero, - }, - hats: [ - { - maxSupply: 1, - details: "", - imageURI: "", - isMutable: false, - wearer: ethers.constants.AddressZero, - }, - { - maxSupply: 1, - details: "", - imageURI: "", - isMutable: false, - wearer: ethers.constants.AddressZero, - }, - ], - }, - ] - ), - signers: [dao], - }); - }); - - it("Emits an ExecutionSuccess event", async () => { - await expect(createAndDeclareTreeTx).to.emit( - gnosisSafe, - "ExecutionSuccess" - ); - }); - - it("Emits an ExecutionFromModuleSuccess event", async () => { - await expect(createAndDeclareTreeTx) - .to.emit(gnosisSafe, "ExecutionFromModuleSuccess") - .withArgs(decentHatsAddress); - }); - - it("Emits some hatsTreeId ValueUpdated events", async () => { - await expect(createAndDeclareTreeTx) - .to.emit(keyValuePairs, "ValueUpdated") - .withArgs(gnosisSafeAddress, "topHatId", "0"); - }); - - describe("Multiple calls", () => { - let createAndDeclareTreeTx2: ethers.ContractTransaction; - - beforeEach(async () => { - createAndDeclareTreeTx2 = await executeSafeTransaction({ - safe: gnosisSafe, - to: decentHatsAddress, - transactionData: - DecentHats_0_1_0__factory.createInterface().encodeFunctionData( - "createAndDeclareTree", - [ - { - hatsProtocol: mockHatsAddress, - hatsAccountImplementation: - mockHatsAccountImplementationAddress, - registry: erc6551Registry.address, - keyValuePairs: keyValuePairs.address, - topHatDetails: "", - topHatImageURI: "", - adminHat: { - maxSupply: 1, - details: "", - imageURI: "", - isMutable: false, - wearer: ethers.constants.AddressZero, - }, - hats: [], - }, - ] - ), - signers: [dao], - }); - }); - - it("Emits an ExecutionSuccess event", async () => { - await expect(createAndDeclareTreeTx2).to.emit( - gnosisSafe, - "ExecutionSuccess" - ); - }); - - it("Emits an ExecutionFromModuleSuccess event", async () => { - await expect(createAndDeclareTreeTx2) - .to.emit(gnosisSafe, "ExecutionFromModuleSuccess") - .withArgs(decentHatsAddress); - }); - - it("Creates Top Hats with sequential IDs", async () => { - await expect(createAndDeclareTreeTx2) - .to.emit(keyValuePairs, "ValueUpdated") - .withArgs(gnosisSafeAddress, "topHatId", "4"); - }); - }); - - describe("Creating Hats Accounts", () => { - let salt: string; - - beforeEach(async () => { - salt = solidityKeccak256( - ["string", "uint256", "address"], - ["DecentHats_0_1_0", await hre.getChainId(), decentHatsAddress] - ); - }); - - const getHatAccount = async (hatId: bigint) => { - const hatAccountAddress = await erc6551Registry.account( - mockHatsAccountImplementationAddress, - salt, - await hre.getChainId(), - mockHatsAddress, - hatId - ); - - const hatAccount = MockHatsAccount__factory.connect( - hatAccountAddress, - hre.ethers.provider - ); - - return hatAccount; - }; - - it("Generates the correct Addresses for the current Hats", async () => { - const currentCount = await mockHats.count(); - - for ( - let i = ethers.BigNumber.from(0); - i.lt(currentCount); - i = i.add(1) - ) { - const foo = BigInt(i.toString()); - const topHatAccount = await getHatAccount(foo); - expect(await topHatAccount.tokenId()).eq(i); - expect(await topHatAccount.tokenImplementation()).eq( - mockHatsAddress - ); - } - }); - }); - }); - }); -}); diff --git a/test/DecentHats_0_1_0.test.ts b/test/DecentHats_0_1_0.test.ts new file mode 100644 index 00000000..afaa5c95 --- /dev/null +++ b/test/DecentHats_0_1_0.test.ts @@ -0,0 +1,617 @@ +import { + GnosisSafeL2, + GnosisSafeL2__factory, + DecentHats_0_1_0__factory, + KeyValuePairs, + KeyValuePairs__factory, + MockHats__factory, + ERC6551Registry__factory, + MockHatsAccount__factory, + ERC6551Registry, + DecentHats_0_1_0, + MockHatsAccount, + MockHats, + MockSablierV2LockupLinear__factory, + MockSablierV2LockupLinear, + MockERC20__factory, + MockERC20, +} from "../typechain-types"; + +import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; +import { expect } from "chai"; +import { ethers, solidityPackedKeccak256 } from "ethers"; +import hre from "hardhat"; + +import { + getGnosisSafeL2Singleton, + getGnosisSafeProxyFactory, +} from "./GlobalSafeDeployments.test"; +import { + buildSafeTransaction, + buildSignatureBytes, + predictGnosisSafeAddress, + safeSignTypedData, +} from "./helpers"; + +const executeSafeTransaction = async ({ + safe, + to, + transactionData, + signers, +}: { + safe: GnosisSafeL2; + to: string; + transactionData: string; + signers: SignerWithAddress[]; +}) => { + const safeTx = buildSafeTransaction({ + to, + data: transactionData, + nonce: await safe.nonce(), + }); + + const sigs = await Promise.all( + signers.map(async (signer) => await safeSignTypedData(signer, safe, safeTx)) + ); + + const tx = await safe.execTransaction( + safeTx.to, + safeTx.value, + safeTx.data, + safeTx.operation, + safeTx.safeTxGas, + safeTx.baseGas, + safeTx.gasPrice, + safeTx.gasToken, + safeTx.refundReceiver, + buildSignatureBytes(sigs) + ); + + return tx; +}; + +describe("DecentHats_0_1_0", () => { + let dao: SignerWithAddress; + + let mockHats: MockHats; + let mockHatsAddress: string; + + let keyValuePairs: KeyValuePairs; + let gnosisSafe: GnosisSafeL2; + + let decentHats: DecentHats_0_1_0; + let decentHatsAddress: string; + + let gnosisSafeAddress: string; + let erc6551Registry: ERC6551Registry; + + let mockHatsAccountImplementation: MockHatsAccount; + let mockHatsAccountImplementationAddress: string; + + let mockSablier: MockSablierV2LockupLinear; + let mockSablierAddress: string; + + let mockERC20: MockERC20; + let mockERC20Address: string; + + beforeEach(async () => { + const signers = await hre.ethers.getSigners(); + const [deployer] = signers; + [, dao] = signers; + + mockHats = await new MockHats__factory(deployer).deploy(); + mockHatsAddress = await mockHats.getAddress(); + keyValuePairs = await new KeyValuePairs__factory(deployer).deploy(); + erc6551Registry = await new ERC6551Registry__factory(deployer).deploy(); + mockHatsAccountImplementation = await new MockHatsAccount__factory( + deployer + ).deploy(); + mockHatsAccountImplementationAddress = + await mockHatsAccountImplementation.getAddress(); + decentHats = await new DecentHats_0_1_0__factory(deployer).deploy(); + decentHatsAddress = await decentHats.getAddress(); + + const gnosisSafeProxyFactory = getGnosisSafeProxyFactory(); + const gnosisSafeL2Singleton = getGnosisSafeL2Singleton(); + const gnosisSafeL2SingletonAddress = + await gnosisSafeL2Singleton.getAddress(); + + const createGnosisSetupCalldata = + GnosisSafeL2__factory.createInterface().encodeFunctionData("setup", [ + [dao.address], + 1, + hre.ethers.ZeroAddress, + hre.ethers.ZeroHash, + hre.ethers.ZeroAddress, + hre.ethers.ZeroAddress, + 0, + hre.ethers.ZeroAddress, + ]); + + const saltNum = BigInt( + `0x${Buffer.from(hre.ethers.randomBytes(32)).toString("hex")}` + ); + + const predictedGnosisSafeAddress = await predictGnosisSafeAddress( + createGnosisSetupCalldata, + saltNum, + gnosisSafeL2SingletonAddress, + gnosisSafeProxyFactory + ); + gnosisSafeAddress = predictedGnosisSafeAddress; + + await gnosisSafeProxyFactory.createProxyWithNonce( + gnosisSafeL2SingletonAddress, + createGnosisSetupCalldata, + saltNum + ); + + gnosisSafe = GnosisSafeL2__factory.connect( + predictedGnosisSafeAddress, + deployer + ); + + // Deploy MockSablierV2LockupLinear + mockSablier = await new MockSablierV2LockupLinear__factory( + deployer + ).deploy(); + mockSablierAddress = await mockSablier.getAddress(); + + mockERC20 = await new MockERC20__factory(deployer).deploy( + "MockERC20", + "MCK" + ); + mockERC20Address = await mockERC20.getAddress(); + + await mockERC20.mint(gnosisSafeAddress, ethers.parseEther("1000000")); + }); + + describe("DecentHats as a Module", () => { + let enableModuleTx: ethers.ContractTransactionResponse; + + beforeEach(async () => { + enableModuleTx = await executeSafeTransaction({ + safe: gnosisSafe, + to: gnosisSafeAddress, + transactionData: + GnosisSafeL2__factory.createInterface().encodeFunctionData( + "enableModule", + [decentHatsAddress] + ), + signers: [dao], + }); + }); + + it("Emits an ExecutionSuccess event", async () => { + await expect(enableModuleTx).to.emit(gnosisSafe, "ExecutionSuccess"); + }); + + it("Emits an EnabledModule event", async () => { + await expect(enableModuleTx) + .to.emit(gnosisSafe, "EnabledModule") + .withArgs(decentHatsAddress); + }); + + describe("Creating a new Top Hat and Tree", () => { + let createAndDeclareTreeTx: ethers.ContractTransactionResponse; + + beforeEach(async () => { + createAndDeclareTreeTx = await executeSafeTransaction({ + safe: gnosisSafe, + to: decentHatsAddress, + transactionData: + DecentHats_0_1_0__factory.createInterface().encodeFunctionData( + "createAndDeclareTree", + [ + { + hatsProtocol: mockHatsAddress, + hatsAccountImplementation: + mockHatsAccountImplementationAddress, + registry: await erc6551Registry.getAddress(), + keyValuePairs: await keyValuePairs.getAddress(), + topHatDetails: "", + topHatImageURI: "", + adminHat: { + maxSupply: 1, + details: "", + imageURI: "", + isMutable: false, + wearer: ethers.ZeroAddress, + sablierParams: [], + }, + hats: [ + { + maxSupply: 1, + details: "", + imageURI: "", + isMutable: false, + wearer: ethers.ZeroAddress, + sablierParams: [], + }, + { + maxSupply: 1, + details: "", + imageURI: "", + isMutable: false, + wearer: ethers.ZeroAddress, + sablierParams: [], + }, + ], + }, + ] + ), + signers: [dao], + }); + }); + + it("Emits an ExecutionSuccess event", async () => { + await expect(createAndDeclareTreeTx).to.emit( + gnosisSafe, + "ExecutionSuccess" + ); + }); + + it("Emits an ExecutionFromModuleSuccess event", async () => { + await expect(createAndDeclareTreeTx) + .to.emit(gnosisSafe, "ExecutionFromModuleSuccess") + .withArgs(decentHatsAddress); + }); + + it("Emits some hatsTreeId ValueUpdated events", async () => { + await expect(createAndDeclareTreeTx) + .to.emit(keyValuePairs, "ValueUpdated") + .withArgs(gnosisSafeAddress, "topHatId", "0"); + }); + + describe("Multiple calls", () => { + let createAndDeclareTreeTx2: ethers.ContractTransactionResponse; + + beforeEach(async () => { + createAndDeclareTreeTx2 = await executeSafeTransaction({ + safe: gnosisSafe, + to: decentHatsAddress, + transactionData: + DecentHats_0_1_0__factory.createInterface().encodeFunctionData( + "createAndDeclareTree", + [ + { + hatsProtocol: mockHatsAddress, + hatsAccountImplementation: + mockHatsAccountImplementationAddress, + registry: await erc6551Registry.getAddress(), + keyValuePairs: await keyValuePairs.getAddress(), + topHatDetails: "", + topHatImageURI: "", + adminHat: { + maxSupply: 1, + details: "", + imageURI: "", + isMutable: false, + wearer: ethers.ZeroAddress, + sablierParams: [], + }, + hats: [], + }, + ] + ), + signers: [dao], + }); + }); + + it("Emits an ExecutionSuccess event", async () => { + await expect(createAndDeclareTreeTx2).to.emit( + gnosisSafe, + "ExecutionSuccess" + ); + }); + + it("Emits an ExecutionFromModuleSuccess event", async () => { + await expect(createAndDeclareTreeTx2) + .to.emit(gnosisSafe, "ExecutionFromModuleSuccess") + .withArgs(decentHatsAddress); + }); + + it("Creates Top Hats with sequential IDs", async () => { + await expect(createAndDeclareTreeTx2) + .to.emit(keyValuePairs, "ValueUpdated") + .withArgs(gnosisSafeAddress, "topHatId", "4"); + }); + }); + + describe("Creating Hats Accounts", () => { + let salt: string; + + beforeEach(async () => { + salt = solidityPackedKeccak256( + ["string", "uint256", "address"], + ["DecentHats_0_1_0", await hre.getChainId(), decentHatsAddress] + ); + }); + + const getHatAccount = async (hatId: bigint) => { + const hatAccountAddress = await erc6551Registry.account( + mockHatsAccountImplementationAddress, + salt, + await hre.getChainId(), + mockHatsAddress, + hatId + ); + + const hatAccount = MockHatsAccount__factory.connect( + hatAccountAddress, + hre.ethers.provider + ); + + return hatAccount; + }; + + it("Generates the correct Addresses for the current Hats", async () => { + const currentCount = await mockHats.count(); + + for (let i = 0n; i < currentCount; i++) { + const topHatAccount = await getHatAccount(i); + expect(await topHatAccount.tokenId()).eq(i); + expect(await topHatAccount.tokenImplementation()).eq( + mockHatsAddress + ); + } + }); + }); + }); + + describe("Creating a new Top Hat and Tree with Sablier Streams", () => { + let createAndDeclareTreeTx: ethers.ContractTransactionResponse; + let currentBlockTimestamp: number; + + beforeEach(async () => { + currentBlockTimestamp = (await hre.ethers.provider.getBlock("latest"))! + .timestamp; + + createAndDeclareTreeTx = await executeSafeTransaction({ + safe: gnosisSafe, + to: decentHatsAddress, + transactionData: + DecentHats_0_1_0__factory.createInterface().encodeFunctionData( + "createAndDeclareTree", + [ + { + hatsProtocol: mockHatsAddress, + hatsAccountImplementation: + mockHatsAccountImplementationAddress, + registry: await erc6551Registry.getAddress(), + keyValuePairs: await keyValuePairs.getAddress(), + topHatDetails: "", + topHatImageURI: "", + adminHat: { + maxSupply: 1, + details: "", + imageURI: "", + isMutable: false, + wearer: ethers.ZeroAddress, + sablierParams: [], + }, + hats: [ + { + maxSupply: 1, + details: "", + imageURI: "", + isMutable: false, + wearer: ethers.ZeroAddress, + sablierParams: [ + { + sablier: mockSablierAddress, + sender: gnosisSafeAddress, + totalAmount: ethers.parseEther("100"), + asset: mockERC20Address, + cancelable: true, + transferable: false, + timestamps: { + start: currentBlockTimestamp, + cliff: 0, + end: currentBlockTimestamp + 2592000, // 30 days from now + }, + broker: { account: ethers.ZeroAddress, fee: 0 }, + }, + ], + }, + { + maxSupply: 1, + details: "", + imageURI: "", + isMutable: false, + wearer: ethers.ZeroAddress, + sablierParams: [], + }, + ], + }, + ] + ), + signers: [dao], + }); + }); + + it("Emits an ExecutionSuccess event", async () => { + await expect(createAndDeclareTreeTx).to.emit( + gnosisSafe, + "ExecutionSuccess" + ); + }); + + it("Emits an ExecutionFromModuleSuccess event", async () => { + await expect(createAndDeclareTreeTx) + .to.emit(gnosisSafe, "ExecutionFromModuleSuccess") + .withArgs(decentHatsAddress); + }); + + it("Emits some hatsTreeId ValueUpdated events", async () => { + await expect(createAndDeclareTreeTx) + .to.emit(keyValuePairs, "ValueUpdated") + .withArgs(gnosisSafeAddress, "topHatId", "0"); + }); + + it("Creates a Sablier stream for the hat with stream parameters", async () => { + const streamCreatedEvents = await mockSablier.queryFilter( + mockSablier.filters.StreamCreated() + ); + expect(streamCreatedEvents.length).to.equal(1); + + const event = streamCreatedEvents[0]; + expect(event.args.sender).to.equal(gnosisSafeAddress); + expect(event.args.recipient).to.not.equal(ethers.ZeroAddress); + expect(event.args.totalAmount).to.equal(ethers.parseEther("100")); + }); + + it("Does not create a Sablier stream for hats without stream parameters", async () => { + const streamCreatedEvents = await mockSablier.queryFilter( + mockSablier.filters.StreamCreated() + ); + expect(streamCreatedEvents.length).to.equal(1); // Only one stream should be created + }); + + it("Creates a Sablier stream with correct timestamps", async () => { + const streamCreatedEvents = await mockSablier.queryFilter( + mockSablier.filters.StreamCreated() + ); + expect(streamCreatedEvents.length).to.equal(1); + + const streamId = streamCreatedEvents[0].args.streamId; + const stream = await mockSablier.getStream(streamId); + + expect(stream.startTime).to.equal(currentBlockTimestamp); + expect(stream.endTime).to.equal(currentBlockTimestamp + 2592000); + }); + }); + + describe("Creating a new Top Hat and Tree with Multiple Sablier Streams per Hat", () => { + let currentBlockTimestamp: number; + + beforeEach(async () => { + currentBlockTimestamp = (await hre.ethers.provider.getBlock("latest"))! + .timestamp; + + await executeSafeTransaction({ + safe: gnosisSafe, + to: decentHatsAddress, + transactionData: + DecentHats_0_1_0__factory.createInterface().encodeFunctionData( + "createAndDeclareTree", + [ + { + hatsProtocol: mockHatsAddress, + hatsAccountImplementation: + mockHatsAccountImplementationAddress, + registry: await erc6551Registry.getAddress(), + keyValuePairs: await keyValuePairs.getAddress(), + topHatDetails: "", + topHatImageURI: "", + adminHat: { + maxSupply: 1, + details: "", + imageURI: "", + isMutable: false, + wearer: ethers.ZeroAddress, + sablierParams: [], + }, + hats: [ + { + maxSupply: 1, + details: "", + imageURI: "", + isMutable: false, + wearer: ethers.ZeroAddress, + sablierParams: [ + { + sablier: mockSablierAddress, + sender: gnosisSafeAddress, + totalAmount: ethers.parseEther("100"), + asset: mockERC20Address, + cancelable: true, + transferable: false, + timestamps: { + start: currentBlockTimestamp, + cliff: currentBlockTimestamp + 86400, // 1 day cliff + end: currentBlockTimestamp + 2592000, // 30 days from now + }, + broker: { account: ethers.ZeroAddress, fee: 0 }, + }, + { + sablier: mockSablierAddress, + sender: gnosisSafeAddress, + totalAmount: ethers.parseEther("50"), + asset: mockERC20Address, + cancelable: false, + transferable: true, + timestamps: { + start: currentBlockTimestamp, + cliff: 0, // No cliff + end: currentBlockTimestamp + 1296000, // 15 days from now + }, + broker: { account: ethers.ZeroAddress, fee: 0 }, + }, + ], + }, + ], + }, + ] + ), + signers: [dao], + }); + }); + + it("Creates multiple Sablier streams for a single hat", async () => { + const streamCreatedEvents = await mockSablier.queryFilter( + mockSablier.filters.StreamCreated() + ); + expect(streamCreatedEvents.length).to.equal(2); + + const event1 = streamCreatedEvents[0]; + expect(event1.args.sender).to.equal(gnosisSafeAddress); + expect(event1.args.recipient).to.not.equal(ethers.ZeroAddress); + expect(event1.args.totalAmount).to.equal(ethers.parseEther("100")); + + const event2 = streamCreatedEvents[1]; + expect(event2.args.sender).to.equal(gnosisSafeAddress); + expect(event2.args.recipient).to.equal(event1.args.recipient); + expect(event2.args.totalAmount).to.equal(ethers.parseEther("50")); + }); + + it("Creates streams with correct parameters", async () => { + const streamCreatedEvents = await mockSablier.queryFilter( + mockSablier.filters.StreamCreated() + ); + + const stream1 = await mockSablier.getStream( + streamCreatedEvents[0].args.streamId + ); + expect(stream1.cancelable).to.be.true; + expect(stream1.transferable).to.be.false; + expect(stream1.endTime - stream1.startTime).to.equal(2592000); + + const stream2 = await mockSablier.getStream( + streamCreatedEvents[1].args.streamId + ); + expect(stream2.cancelable).to.be.false; + expect(stream2.transferable).to.be.true; + expect(stream2.endTime - stream2.startTime).to.equal(1296000); + }); + + it("Creates streams with correct timestamps", async () => { + const streamCreatedEvents = await mockSablier.queryFilter( + mockSablier.filters.StreamCreated() + ); + + const stream1 = await mockSablier.getStream( + streamCreatedEvents[0].args.streamId + ); + expect(stream1.startTime).to.equal(currentBlockTimestamp); + expect(stream1.endTime).to.equal(currentBlockTimestamp + 2592000); + + const stream2 = await mockSablier.getStream( + streamCreatedEvents[1].args.streamId + ); + expect(stream2.startTime).to.equal(currentBlockTimestamp); + expect(stream2.endTime).to.equal(currentBlockTimestamp + 1296000); + }); + }); + }); +});