Skip to content

Commit

Permalink
Avoid tokens with 18 decimals to make 1 token = 1 unit
Browse files Browse the repository at this point in the history
  • Loading branch information
sembrestels committed Sep 13, 2024
1 parent ab1fa04 commit 8e51c3a
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 4 deletions.
6 changes: 6 additions & 0 deletions contracts/councilhaus/contracts/Council.sol
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ contract Council is NonTransferableToken, AccessControl, PoolManager {
error GranteeNotFound();
error AmountMustBeGreaterThanZero();
error TotalAllocatedExceedsBalance();
error VotingPowerTooHigh();

// Event definitions
event MaxAllocationsPerMemberSet(uint8 maxAllocationsPerMember);
Expand Down Expand Up @@ -105,6 +106,7 @@ contract Council is NonTransferableToken, AccessControl, PoolManager {
) public onlyRole(MEMBER_MANAGER_ROLE) {
if (balanceOf(_member) > 0) revert CouncilMemberAlreadyAdded();
if (_votingPower == 0) revert AmountMustBeGreaterThanZero();
if (_votingPower > 1e6) revert VotingPowerTooHigh();
_mint(_member, _votingPower);
emit CouncilMemberAdded(_member, _votingPower);
}
Expand Down Expand Up @@ -185,6 +187,10 @@ contract Council is NonTransferableToken, AccessControl, PoolManager {
emit Withdrawn(_token, msg.sender, balance);
}

function decimals() public pure override returns (uint8) {
return 0;
}

/**
* @notice Get the allocation details for a council member
* @param _member Address of the council member
Expand Down
106 changes: 106 additions & 0 deletions contracts/councilhaus/test/integration/pools.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { loadFixture } from "@nomicfoundation/hardhat-toolbox-viem/network-helpers";
import { assert, expect } from "chai";
import hre, { viem } from "hardhat";
import { getAddress, parseEventLogs, parseUnits } from "viem";

// A deployment function to set up the initial state
const deploy = async () => {
const publicClient = await viem.getPublicClient();
const [wallet1, wallet2] = await viem.getWalletClients();

const gdav1ForwarderAddress: `0x${string}` =
"0x6DA13Bde224A05a288748d857b9e7DDEffd1dE08";

const councilFactory = await viem.deployContract("CouncilFactory", [
gdav1ForwarderAddress,
]);

const councilFromTx = async (hash: `0x${string}`) => {
const receipt = await publicClient.getTransactionReceipt({ hash });
const logs = parseEventLogs({
abi: councilFactory.abi,
logs: receipt.logs,
});
return logs[0].args;
};

return {
councilFactory,
publicClient,
wallet1,
wallet2,
addr1: wallet1.account.address,
addr2: wallet2.account.address,
councilFromTx,
gdav1ForwarderAddress,
};
};

describe("Integration Tests: Pools", () => {
before(async () => {
if (!process.env.ALCHEMY_KEY) {
throw new Error("ALCHEMY_KEY is not set");
}
// Switch to the forked network
await hre.network.provider.request({
method: "hardhat_reset",
params: [
{
forking: {
jsonRpcUrl: `https://opt-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_KEY}`,
blockNumber: 125_042_537,
},
},
],
});
});
describe("Deployment", () => {
it("should set the correct GDAv1Forwarder address", async () => {
const { councilFactory, gdav1ForwarderAddress } =
await loadFixture(deploy);
assert.equal(
await councilFactory.read.gdav1Forwarder(),
getAddress(gdav1ForwarderAddress),
);
});
});
describe("createCouncil", () => {
it("should create a new council and emit a CouncilCreated event", async () => {
const { councilFactory, addr1, addr2, councilFromTx } =
await loadFixture(deploy);
const config = {
councilName: "Spacing Guild",
councilSymbol: "SPA",
councilMembers: [
{ account: addr1, votingPower: 50n },
{ account: addr2, votingPower: 100n },
],
grantees: [
{
name: "ENS Wayback Machine",
account:
"0x6ea869B6870dd98552B0C7e47dA90702a436358b" as `0x${string}`,
},
{
name: "Giveth House",
account:
"0xB6989F472Bef8931e6Ca882b1f875539b7D5DA19" as `0x${string}`,
},
{
name: "EVMcrispr",
account:
"0xeafFF6dB1965886348657E79195EB6f1A84657eB" as `0x${string}`,
},
],
distributionToken:
"0x7d342726b69c28d942ad8bfe6ac81b972349d524" as `0x${string}`, // DAIx
};

const hash = await councilFactory.write.createCouncil([config]);

const { council, pool } = await councilFromTx(hash);
expect(council).to.be.a("string");
expect(pool).to.be.a("string");
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ describe("CouncilFactory Contract Tests", () => {
councilName: "Spacing Guild",
councilSymbol: "SPA",
councilMembers: [
{ account: addr1, votingPower: parseUnits("100", 18) },
{ account: addr2, votingPower: parseUnits("200", 18) },
{ account: addr1, votingPower: 500000n },
{ account: addr2, votingPower: 1000000n },
],
grantees: [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { loadFixture } from "@nomicfoundation/hardhat-toolbox-viem/network-helpe
import { expect } from "chai";
import { viem } from "hardhat";
import { getAddress, parseUnits, zeroAddress } from "viem";
import { expectEvent } from "./utils";
import { expectEvent } from "../utils";

const ethxTokenAddress = "0x4ac8bD1bDaE47beeF2D1c6Aa62229509b962Aa0d";

Expand Down Expand Up @@ -62,7 +62,7 @@ describe("Council Contract Tests", () => {
});
});

describe("Non-Transferable Token Tests", () => {
describe("Non-Transferable Token Tests with zero decimals", () => {
it("should revert on token transfer", async () => {
const { council, addr1, addr2 } = await loadFixture(deploy);
await council.write.addCouncilMember([addr1, 100n]);
Expand All @@ -89,6 +89,11 @@ describe("Council Contract Tests", () => {
council.write.approve([addr2, 50n], { account: addr1 }),
).to.be.rejectedWith("CantApproveToken");
});

it("should return the correct decimals", async () => {
const { council } = await loadFixture(deploy);
expect(await council.read.decimals()).to.equal(0);
});
});

describe("Role Management", () => {
Expand Down Expand Up @@ -199,6 +204,13 @@ describe("Council Contract Tests", () => {
).to.be.rejectedWith("AmountMustBeGreaterThanZero");
});

it("Should revert if adding a council member with a voting power greater than 1M", async () => {
const { council, addr2 } = await loadFixture(deploy);
await expect(
council.write.addCouncilMember([addr2, 1000001n]),
).to.be.rejectedWith("VotingPowerTooHigh");
});

it("Should revert if adding or removing a council member from a non-MEMBER_MANAGER_ROLE", async () => {
const { council, addr2 } = await loadFixture(deploy);
await expect(
Expand Down

0 comments on commit 8e51c3a

Please sign in to comment.