Skip to content

Commit

Permalink
Deploy instances of Smart Accounts for the newly created Hats
Browse files Browse the repository at this point in the history
  • Loading branch information
adamgall committed Jun 26, 2024
1 parent 382acab commit d19d13d
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 9 deletions.
35 changes: 34 additions & 1 deletion contracts/DecentHats.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity =0.8.19;
import {Enum} from "@gnosis.pm/zodiac/contracts/core/Module.sol";
import {IAvatar} from "@gnosis.pm/zodiac/contracts/interfaces/IAvatar.sol";
import {IHats} from "./interfaces/hats/IHats.sol";
import {IERC6551Registry} from "./interfaces/IERC6551Registry.sol";
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";

contract DecentHats {
Expand All @@ -19,10 +20,21 @@ contract DecentHats {

IHats public hats;
address public keyValuePairs;
IERC6551Registry public registry;
address public hatsAccountImplementation;

constructor(IHats _hats, address _keyValuePairs) {
bytes32 public constant SALT = bytes32(abi.encode(0xdece974a75));

constructor(
IHats _hats,
address _keyValuePairs,
IERC6551Registry _registry,
address _hatsAccountImplementation
) {
hats = _hats;
keyValuePairs = _keyValuePairs;
registry = _registry;
hatsAccountImplementation = _hatsAccountImplementation;
}

function createAndDeclareTree(
Expand All @@ -36,6 +48,13 @@ contract DecentHats {
_topHatDetails,
_topHatImageURI
);
registry.createAccount(
hatsAccountImplementation,
SALT,
block.chainid,
address(hats),
topHatId
);

string[] memory keys = new string[](1);
keys[0] = "hatsTreeId";
Expand Down Expand Up @@ -63,6 +82,13 @@ contract DecentHats {
_adminHat.isMutable,
_adminHat.imageURI
);
registry.createAccount(
hatsAccountImplementation,
SALT,
block.chainid,
address(hats),
adminHatId
);

if (_adminHat.wearer != address(0)) {
hats.mintHat(adminHatId, _adminHat.wearer);
Expand All @@ -79,6 +105,13 @@ contract DecentHats {
hat.isMutable,
hat.imageURI
);
registry.createAccount(
hatsAccountImplementation,
SALT,
block.chainid,
address(hats),
hatId
);

if (hat.wearer != address(0)) {
hats.mintHat(hatId, hat.wearer);
Expand Down
75 changes: 67 additions & 8 deletions test/DecentHats.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ import {
KeyValuePairs,
KeyValuePairs__factory,
MockHats__factory,
ERC6551Registry__factory,
MockHatsAccount__factory,
ERC6551Registry,
DecentHats,
MockHatsAccount,
MockHats,
} from "../typechain-types";

import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers";
Expand Down Expand Up @@ -63,26 +69,40 @@ const executeSafeTransaction = async ({
describe("DecentHats", () => {
let dao: SignerWithAddress;

let mockHats: MockHats;
let mockHatsAddress: string;

let keyValuePairs: KeyValuePairs;
let gnosisSafe: GnosisSafeL2;

let gnosisSafeAddress: string;
let decentHats: DecentHats;
let decentHatsAddress: string;

const saltNum = BigInt(
`0x${Buffer.from(ethers.randomBytes(32)).toString("hex")}`
);
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;

const hats = await new MockHats__factory(deployer).deploy();
mockHats = await new MockHats__factory(deployer).deploy();
mockHatsAddress = await mockHats.getAddress();
keyValuePairs = await new KeyValuePairs__factory(deployer).deploy();
const decentHats = await new DecentHats__factory(deployer).deploy(
await hats.getAddress(),
await keyValuePairs.getAddress()
erc6551Registry = await new ERC6551Registry__factory(deployer).deploy();
mockHatsAccountImplementation = await new MockHatsAccount__factory(
deployer
).deploy();
mockHatsAccountImplementationAddress =
await mockHatsAccountImplementation.getAddress();
decentHats = await new DecentHats__factory(deployer).deploy(
mockHatsAddress,
await keyValuePairs.getAddress(),
await erc6551Registry.getAddress(),
mockHatsAccountImplementationAddress
);
decentHatsAddress = await decentHats.getAddress();

Expand All @@ -103,6 +123,10 @@ describe("DecentHats", () => {
ethers.ZeroAddress,
]);

const saltNum = BigInt(
`0x${Buffer.from(ethers.randomBytes(32)).toString("hex")}`
);

const predictedGnosisSafeAddress = await predictGnosisSafeAddress(
createGnosisSetupCalldata,
saltNum,
Expand Down Expand Up @@ -264,6 +288,41 @@ describe("DecentHats", () => {
.withArgs(gnosisSafeAddress, "hatsTreeId", "4");
});
});

describe("Creating Hats Accounts", () => {
let salt: string;

beforeEach(async () => {
salt = await decentHats.SALT();
});

const getHatAccount = async (hatId: number) => {
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 three Hats", async () => {
for (let i = 0; i < 3; i++) {
const topHatAccount = await getHatAccount(i);
expect(await topHatAccount.tokenId()).eq(i);
expect(await topHatAccount.tokenImplementation()).eq(
mockHatsAddress
);
}
});
});
});
});
});

0 comments on commit d19d13d

Please sign in to comment.