Skip to content

Commit

Permalink
Merge pull request #119 from Hats-Protocol/deploy/v1
Browse files Browse the repository at this point in the history
deploy v1
  • Loading branch information
spengrah authored Mar 20, 2023
2 parents 7509b70 + 8f1aae4 commit 4cf4170
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 21 deletions.
27 changes: 19 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,13 +147,13 @@ To avoid confusion, Hats Protocol does not claim to be ERC1155-compliant. Instea
Each Hat has several properties:

* `id` - the integer identifier for the Hat, which also serves as the ERC1155-similar token id (see three paragraphs below)
* `details` - metadata about the Hat; such as a name, description, and other properties like roles and responsibilities associated with the Hat
* `details` - metadata about the Hat; such as a name, description, and other properties like roles and responsibilities associated with the Hat. Should not exceed 7,000 characters.
* `maxSupply` - the maximum number of addresses that can wear the Hat at once
* `admin` - the Hat that controls who can wear the Hat
* `eligibility` - the address that controls eligibility criteria and whether a given wearer of the Hat is in good standing
* `toggle` - the address that controls whether the Hat is active
* `mutable` - whether the hat's properties can be changed by the admin
* `imageURI` - the URI for the image used in the Hat's ERC1155-similar token
* `imageURI` - the URI for the image used in the Hat's ERC1155-similar token. Should not exceed 7,000 characters.

For more information on each property, refer to the detailed sections below.

Expand Down Expand Up @@ -304,7 +304,7 @@ Changes are allowed to the following Hat properties:

Additionally, mutable hats can be transferred by their admins to a different wearer. Immutable hats cannot be transferred.

#### Tophat Exception
#### TopHat Exception

The only exception to the above mutability rules is for tophats, which despite being immutable are allowed to change their own `details` and `imageURI` (but not other properties).

Expand Down Expand Up @@ -346,7 +346,7 @@ To create a batch of Hats, a DAO can call the `Hats.batchCreateHats()` function.

Only a Hat's admin can mint its token to a wearer.

To mint a Hat, the Hat's max supply must not have already been reached, the target wearer must not already wear the Hat, and the target wearer must be eligible for the hat.
To mint a Hat, the Hat must be active, its max supply must not have already been reached, the target wearer must not already wear the Hat, and the target wearer must be eligible for the Hat.

A Hat's admin can mint its token individually by calling `Hats.mintHat`.

Expand All @@ -368,18 +368,29 @@ For these reasons, in Hats Protocol, the standard ERC1155 transfer functions &md

As a replacement, Hats can be transfered by admins via `Hats.transferHat`, which emits the ERC1155 standard event `TransferSingle`. Transfer recipients must not already be wearing the hat, and must be eligible to wear the hat.

With the exception of tophats — which can always transfer themselves — only mutable Hats can be transferred.
With the exception of tophats — which can always transfer themselves — only mutable Hats can be transferred. Inactive Hats cannot be transferred.

### Hat Tree Grafting

Not all Hats trees will unfurl from top down or inside out. Sometimes, new branches will form independently from the main tree, or multiple trees will form before a main tree even exists.

In these cases, Hat trees can be grafted onto other trees. This is done by the wearer of one tree's tophat linking their tophat to a hat in another tree, via `Hats.linkTopHatToTree`. This has two main effects:
In these cases, Hat trees can be grafted onto other trees. This is done via a request-approve process where the wearer of one tree's topHat requests to link their topHat to a hat in another tree, whose admin can approve if desired. This has three main effects:

1. The linked tophat loses its tophat status (i.e., `Hats.isTopHat` will return `false`) and turns into what we call a "tree root", and
1. The linked tophat loses its topHat status (i.e., `Hats.isTopHat` will return `false`) and turns into what we call a "tree root" or "linked topHat", and
2. The hat to which it is linked becomes its new admin; it is no longer its own admin
3. On linking, the linked topHat can be assigned eligibility and/or toggle modules like any other hat

Linked Hat trees can also be unlinked by the tree root from its linked admin, via `Hats.unlinkTopHatFromTree`. This causes the tree root to regain its status as a top hat and to once again become its own admin.
Linked Hat trees can also be unlinked by the tree root from its linked admin, via `Hats.unlinkTopHatFromTree`. This causes the tree root to regain its status as a top hat and to once again become its own admin. Any eligibility or toggle modules added on linking are cleared.

⚠️ **CAUTION**: Be careful when nesting multiple Hat trees. If the nested linkages become too long, the higher level admins may lose control of the lowest level Hats because admin actions at that distance may cost-prohibitive or even exceed the gas limit. Best practice is to not attach external authorities (e.g. via token gating) to Hats in trees that are more than ~10 nested trees deep (varies by network).

#### Relinking

Linked topHats can be relinked to a different Hat within the same tree. This is useful for DAOs that want to reorganize their subtrees without having to go through the request and approve steps. Valid relinks must meet the following criteria in order to ensure security:

1. The Hat wearer executing the relink is an admin of both the linked topHat and the new admin (destination)
2. The new admin (destination) is within the same local tree as the existing admin (origin), or within the tippy top hat's local tree. Tippy top hats executing a relink are not subject to these restrictions.
3. The new link does not create a circular linkage.

### Renouncing a Hat

Expand Down
7 changes: 6 additions & 1 deletion example.env
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
GOERLI_RPC=
SEPOLIA_RPC=
ETHEREUM_RPC=
GC_RPC=
POLYGON_RPC=
OPTIMISM_RPC=
ARBITRUM_RPC=
export PRIVATE_KEY=
ETHERSCAN_KEY=
GNOSISSCAN_KEY=
POLYGONSCAN_KEY=
POLYGONSCAN_KEY=
OPTIMISM_KEY=
ARBISCAN_KEY=
17 changes: 10 additions & 7 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,23 @@ wrap_comments = false
book = "./book.toml"

[rpc_endpoints]
ethereum = "${ETHEREUM_RPC}"
optimism = "${OPTIMISM_RPC}"
goerli = "${GOERLI_RPC}"
arbitrum = "${ARBITRUM_RPC}"
gnosis = "${GC_RPC}"
polygon = "${POLYGON_RPC}"
goerli = "${GOERLI_RPC}"
local = "http://localhost:8545"
mainnet = "${ETHEREUM_RPC}"
optimism = "${OPTIMISM_RPC}"
polygon = "${POLYGON_RPC}"
sepolia = "${SEPOLIA_RPC}"

[etherscan]
arbitrum = {key = "${ARBISCAN_KEY}", url = "https://api.arbiscan.io/api"}
goerli = {key = "${ETHERSCAN_KEY}", url = "https://api-goerli.etherscan.io/api"}
ethereum = {key = "${ETHERSCAN_KEY}", chain = "mainnet"}
optimism = {key = "${OPTIMISM_ETHERSCAN_KEY}", url = "https://api-optimistic.etherscan.io/api"}
polygon = {key = "${POLYGONSCAN_KEY}", url = "https://api.polygonscan.com/api"}
gnosis = {key = "${GNOSISSCAN_KEY}", url = "https://api.gnosisscan.io/api"}
mainnet = {key = "${ETHERSCAN_KEY}", url = "https://api.etherscan.io/api"}
optimism = {key = "${OPTIMISM_KEY}", url = "https://api-optimistic.etherscan.io/api"}
sepolia = {key = "${ETHERSCAN_KEY}", url = "https://api-sepolia.etherscan.io/api"}
polygon = {key = "${POLYGONSCAN_KEY}", url = "https://api.polygonscan.com/api"}


# See more config options https://github.com/foundry-rs/foundry/tree/master/config
20 changes: 15 additions & 5 deletions script/Hats.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,42 @@ import { Hats } from "../src/Hats.sol";
contract DeployHats is Script {
string public constant baseImageURI = "ipfs://bafybeigcimbqwfajsnhoq7fqnbdllz7kye7cpdy3adj2sob3wku2llu5bi";

string public constant name = "Hats Protocol v1-beta1"; // increment this each deployment
string public constant name = "Hats Protocol v1"; // increment this each deployment

bytes32 internal constant SALT = bytes32(abi.encode(0x4a75)); // ~ H(4) A(a) T(7) S(5)

function run() external {
uint256 privKey = vm.envUint("PRIVATE_KEY");

address deployer = vm.rememberKey(privKey);
console2.log(vm.getNonce(deployer));
console2.log("Deployer: ", deployer);
console2.log("Deployer Nonce: ", vm.getNonce(deployer));

vm.startBroadcast(deployer);

// deploy Hats
Hats hats = new Hats{ salt: SALT }(name, baseImageURI);

// mint Hats Protocol Governance topHat
// Note: This topHat is not connected to any protocol authorities. The protocol is fully permissionless and not upgradeable.
hats.mintTopHat(
0x2D785497c6C8ce3f4cCff4937D321C37e80705E8, // hatsprotocol.eth
"Hats Protocol Governance",
baseImageURI
);

vm.stopBroadcast();

console2.log("Salt: ", vm.toString(SALT));
console2.log("Hats contract: ", address(hats));
}

// forge script script/Hats.s.sol:DeployHats -f goerli
// forge script script/Hats.s.sol:DeployHats -f goerli --broadcast --verify
// forge script script/Hats.s.sol:DeployHats -f ethereum
// forge script script/Hats.s.sol:DeployHats -f ethereum --broadcast --verify

// forge script script/Hats.s.sol:DeployHats --rpc-url http://localhost:8545 --broadcast

// forge verify-contract --chain-id 5 --num-of-optimizations 10000 --watch --constructor-args $(cast abi-encode "constructor(string,string)" "Hats Protocol v1-beta1" "ipfs://bafybeigcimbqwfajsnhoq7fqnbdllz7kye7cpdy3adj2sob3wku2llu5bi") --compiler-version v0.8.17 0x96bD657Fcc04c71B47f896a829E5728415cbcAa1 src/Hats.sol:Hats $ETHERSCAN_KEY
// forge verify-contract --chain-id 1 --num-of-optimizations 10000 --watch --constructor-args $(cast abi-encode "constructor(string,string)" "Hats Protocol v1" "ipfs://bafybeigcimbqwfajsnhoq7fqnbdllz7kye7cpdy3adj2sob3wku2llu5bi") --compiler-version v0.8.17 0x850f3384829D7bab6224D141AFeD9A559d745E3D src/Hats.sol:Hats --etherscan-api-key $ETHERSCAN_KEY
}

contract DeployHatsAndMintTopHat is Script {
Expand Down

0 comments on commit 4cf4170

Please sign in to comment.