import { expect } from "chai" import { ethers } from "hardhat" import { ControlledERC20 } from "../typechain-types" describe("ControlledERC20", function () { let controlledERC20: ControlledERC20 let owner: any let user1: any let user2: any let user3: any const MINTER_ROLE = ethers.keccak256(ethers.toUtf8Bytes("MINTER_ROLE")) const PAUSER_ROLE = ethers.keccak256(ethers.toUtf8Bytes("PAUSER_ROLE")) const TRANSFER_CONTROLLER_ROLE = ethers.keccak256(ethers.toUtf8Bytes("TRANSFER_CONTROLLER_ROLE")) beforeEach(async function () { ;[owner, user1, user2, user3] = await ethers.getSigners() const ControlledERC20Factory = await ethers.getContractFactory("ControlledERC20") controlledERC20 = await ControlledERC20Factory.deploy("Controlled Token", "CTRL", owner.address) }) describe("Deployment", function () { it("Should set the right owner with all roles", async function () { expect(await controlledERC20.hasRole(ethers.ZeroHash, owner.address)).to.be.true // DEFAULT_ADMIN_ROLE expect(await controlledERC20.hasRole(MINTER_ROLE, owner.address)).to.be.true expect(await controlledERC20.hasRole(PAUSER_ROLE, owner.address)).to.be.true expect(await controlledERC20.hasRole(TRANSFER_CONTROLLER_ROLE, owner.address)).to.be.true }) it("Should have transfer enabled by default", async function () { expect(await controlledERC20.transferEnabled()).to.be.true }) it("Should have owner in whitelist", async function () { expect(await controlledERC20.isWhitelisted(owner.address)).to.be.true }) }) describe("Role Management", function () { it("Should allow admin to grant minter role", async function () { await controlledERC20.connect(owner).grantRole(MINTER_ROLE, user1.address) expect(await controlledERC20.hasRole(MINTER_ROLE, user1.address)).to.be.true }) it("Should allow admin to revoke minter role", async function () { await controlledERC20.connect(owner).grantRole(MINTER_ROLE, user1.address) await controlledERC20.connect(owner).revokeRole(MINTER_ROLE, user1.address) expect(await controlledERC20.hasRole(MINTER_ROLE, user1.address)).to.be.false }) }) describe("Minting", function () { it("Should allow minter to mint tokens", async function () { const mintAmount = ethers.parseEther("1000") await controlledERC20.connect(owner).mint(user1.address, mintAmount) expect(await controlledERC20.balanceOf(user1.address)).to.equal(mintAmount) }) it("Should allow minter to batch mint tokens", async function () { const recipients = [user1.address, user2.address] const amounts = [ethers.parseEther("100"), ethers.parseEther("200")] await controlledERC20.connect(owner).mintBatch(recipients, amounts) expect(await controlledERC20.balanceOf(user1.address)).to.equal(amounts[0]) expect(await controlledERC20.balanceOf(user2.address)).to.equal(amounts[1]) }) it("Should not allow non-minter to mint", async function () { const mintAmount = ethers.parseEther("1000") await expect(controlledERC20.connect(user1).mint(user2.address, mintAmount)).to.be.revertedWithCustomError( controlledERC20, "AccessControlUnauthorizedAccount" ) }) }) describe("Transfer Control", function () { beforeEach(async function () { // Mint some tokens to users for testing await controlledERC20.connect(owner).mint(user1.address, ethers.parseEther("1000")) await controlledERC20.connect(owner).mint(user2.address, ethers.parseEther("1000")) }) it("Should allow transfer when enabled", async function () { const transferAmount = ethers.parseEther("100") await controlledERC20.connect(user1).transfer(user3.address, transferAmount) expect(await controlledERC20.balanceOf(user3.address)).to.equal(transferAmount) }) it("Should not allow transfer when disabled", async function () { await controlledERC20.connect(owner).setTransferEnabled(false) const transferAmount = ethers.parseEther("100") await expect(controlledERC20.connect(user1).transfer(user3.address, transferAmount)).to.be.revertedWith( "Transfer is disabled" ) }) it("Should allow whitelisted addresses to transfer when disabled", async function () { await controlledERC20.connect(owner).setTransferEnabled(false) await controlledERC20.connect(owner).updateWhitelist(user1.address, true) const transferAmount = ethers.parseEther("100") await controlledERC20.connect(user1).transfer(user3.address, transferAmount) expect(await controlledERC20.balanceOf(user3.address)).to.equal(transferAmount) }) it("Should allow transfer to whitelisted addresses when disabled", async function () { await controlledERC20.connect(owner).setTransferEnabled(false) await controlledERC20.connect(owner).updateWhitelist(user3.address, true) const transferAmount = ethers.parseEther("100") await controlledERC20.connect(user1).transfer(user3.address, transferAmount) expect(await controlledERC20.balanceOf(user3.address)).to.equal(transferAmount) }) }) describe("Whitelist Management", function () { it("Should allow transfer controller to update whitelist", async function () { await controlledERC20.connect(owner).updateWhitelist(user1.address, true) expect(await controlledERC20.isWhitelisted(user1.address)).to.be.true }) it("Should allow transfer controller to batch update whitelist", async function () { const accounts = [user1.address, user2.address] const isWhitelisted = [true, false] await controlledERC20.connect(owner).updateWhitelistBatch(accounts, isWhitelisted) expect(await controlledERC20.isWhitelisted(user1.address)).to.be.true expect(await controlledERC20.isWhitelisted(user2.address)).to.be.false }) it("Should not allow non-transfer controller to update whitelist", async function () { await expect( controlledERC20.connect(user1).updateWhitelist(user2.address, true) ).to.be.revertedWithCustomError(controlledERC20, "AccessControlUnauthorizedAccount") }) }) describe("Pause/Unpause", function () { it("Should allow pauser to pause", async function () { await controlledERC20.connect(owner).pause() expect(await controlledERC20.paused()).to.be.true }) it("Should allow pauser to unpause", async function () { await controlledERC20.connect(owner).pause() await controlledERC20.connect(owner).unpause() expect(await controlledERC20.paused()).to.be.false }) it("Should not allow non-pauser to pause", async function () { await expect(controlledERC20.connect(user1).pause()).to.be.revertedWithCustomError( controlledERC20, "AccessControlUnauthorizedAccount" ) }) }) describe("Burn", function () { beforeEach(async function () { await controlledERC20.connect(owner).mint(user1.address, ethers.parseEther("1000")) }) it("Should allow burning tokens", async function () { const burnAmount = ethers.parseEther("100") const initialBalance = await controlledERC20.balanceOf(user1.address) await controlledERC20.connect(user1).burn(burnAmount) expect(await controlledERC20.balanceOf(user1.address)).to.equal(initialBalance - burnAmount) }) }) })