@vechain/vebetterdao-contracts
Version:
Open-source repository that houses the smart contracts powering the decentralized VeBetterDAO on the VeChain Thor blockchain.
179 lines (178 loc) • 10.9 kB
JavaScript
import { ethers } from "hardhat";
import { expect } from "chai";
import { catchRevert, getOrDeployContractInstances } from "./helpers";
import { describe, it } from "mocha";
import { createLocalConfig } from "@repo/config/contracts/envs/local";
describe("B3TR Token - @shard0", function () {
describe("Deployment", function () {
it("should deploy the contract", async function () {
const { b3tr } = await getOrDeployContractInstances({ forceDeploy: false });
await b3tr.waitForDeployment();
const address = await b3tr.getAddress();
expect(address).not.to.eql(undefined);
});
it("should have the correct name", async function () {
const { b3tr } = await getOrDeployContractInstances({ forceDeploy: false });
const res = await b3tr.name();
expect(res).to.eql("B3TR");
const res2 = await b3tr.symbol();
expect(res2).to.eql("B3TR");
});
it("should have the correct max supply", async function () {
const config = createLocalConfig();
const { b3tr } = await getOrDeployContractInstances({ forceDeploy: false, config });
const cap = await b3tr.cap();
expect(cap).to.eql(ethers.parseEther("1000243154"));
});
it("admin role is set correctly upon deploy", async function () {
const { b3tr, owner } = await getOrDeployContractInstances({ forceDeploy: false });
const defaultAdminRole = await b3tr.DEFAULT_ADMIN_ROLE();
const res = await b3tr.hasRole(defaultAdminRole, owner);
expect(res).to.eql(true);
});
it("minter role is set correctly upon deploy", async function () {
const { b3tr, otherAccount, minterAccount } = await getOrDeployContractInstances({ forceDeploy: false });
const operatorRole = await b3tr.MINTER_ROLE();
const res = await b3tr.hasRole(operatorRole, minterAccount);
expect(res).to.eql(true);
// test that operator role is not set for other accounts
expect(await b3tr.hasRole(operatorRole, otherAccount)).to.eql(false);
});
it("should revert if default admin set to zero address on initilisation", async function () {
const { owner, minterAccount } = await getOrDeployContractInstances({ forceDeploy: false });
const B3trContract = await ethers.getContractFactory("B3TR");
await expect(B3trContract.deploy(ethers.ZeroAddress, minterAccount, owner)).to.be.reverted;
});
});
describe("Access Control", function () {
it("only admin can grant minter role", async function () {
const { b3tr, owner, otherAccount } = await getOrDeployContractInstances({
forceDeploy: true,
});
const operatorRole = await b3tr.MINTER_ROLE();
expect(await b3tr.hasRole(operatorRole, otherAccount)).to.eql(false);
await expect(b3tr.connect(otherAccount).grantRole(operatorRole, otherAccount)).to.be.reverted;
await b3tr.connect(owner).grantRole(operatorRole, otherAccount);
expect(await b3tr.hasRole(operatorRole, otherAccount)).to.eql(true);
});
it("only admin can revoke minter role", async function () {
const { b3tr, owner, otherAccount } = await getOrDeployContractInstances({ forceDeploy: false });
const operatorRole = await b3tr.MINTER_ROLE();
await b3tr.connect(owner).grantRole(operatorRole, otherAccount);
expect(await b3tr.hasRole(operatorRole, otherAccount)).to.eql(true);
await expect(b3tr.connect(otherAccount).revokeRole(operatorRole, otherAccount)).to.be.reverted;
await b3tr.connect(owner).revokeRole(operatorRole, otherAccount);
expect(await b3tr.hasRole(operatorRole, otherAccount)).to.eql(false);
});
it("only admin can grant admin role", async function () {
const { b3tr, owner, otherAccount } = await getOrDeployContractInstances({ forceDeploy: false });
const adminRole = await b3tr.DEFAULT_ADMIN_ROLE();
// at the beginning owner is admin
expect(await b3tr.hasRole(adminRole, otherAccount)).to.eql(false);
expect(await b3tr.hasRole(adminRole, owner)).to.eql(true);
await expect(b3tr.connect(otherAccount).grantRole(adminRole, otherAccount)).to.be.reverted;
await b3tr.connect(owner).grantRole(adminRole, otherAccount);
expect(await b3tr.hasRole(adminRole, otherAccount)).to.eql(true);
// owner is still admin until it is revoked
expect(await b3tr.hasRole(adminRole, owner)).to.eql(true);
});
it("only admin can revoke admin role", async function () {
const { b3tr, owner, otherAccount, minterAccount } = await getOrDeployContractInstances({ forceDeploy: false });
const adminRole = await b3tr.DEFAULT_ADMIN_ROLE();
// after last test both owner and otherAccount are admin
expect(await b3tr.hasRole(adminRole, otherAccount)).to.eql(true);
expect(await b3tr.hasRole(adminRole, owner)).to.eql(true);
await expect(b3tr.connect(minterAccount).revokeRole(adminRole, owner)).to.be.reverted;
await b3tr.connect(otherAccount).revokeRole(adminRole, owner);
// owner is no longer admin
expect(await b3tr.hasRole(adminRole, owner)).to.eql(false);
// otherAccount is still admin until
expect(await b3tr.hasRole(adminRole, otherAccount)).to.eql(true);
});
it("admin transfer admin permissions to another account", async function () {
const { b3tr, owner, otherAccounts } = await getOrDeployContractInstances({
forceDeploy: true,
});
const adminRole = await b3tr.DEFAULT_ADMIN_ROLE();
const minterRole = await b3tr.MINTER_ROLE();
const newAdmin = otherAccounts[5];
expect(await b3tr.hasRole(adminRole, owner)).to.eql(true);
expect(await b3tr.hasRole(adminRole, newAdmin)).to.eql(false);
await b3tr.connect(owner).grantRole(adminRole, newAdmin);
expect(await b3tr.hasRole(adminRole, newAdmin)).to.eql(true);
await b3tr.connect(owner).renounceRole(adminRole, owner);
expect(await b3tr.hasRole(adminRole, owner)).to.eql(false);
expect(await b3tr.hasRole(adminRole, newAdmin)).to.eql(true);
//can do same stuff as previous owner
await b3tr.connect(newAdmin).grantRole(minterRole, otherAccounts[5]);
await b3tr.connect(newAdmin).grantRole(adminRole, otherAccounts[5]);
});
it("Only admin with PAUSER_ROLE can toggle pause of b3tr transfers", async function () {
const { b3tr, otherAccount, owner } = await getOrDeployContractInstances({ forceDeploy: true });
expect(await b3tr.hasRole(await b3tr.PAUSER_ROLE(), otherAccount.address)).to.eql(false);
await catchRevert(b3tr.connect(otherAccount).pause());
await catchRevert(b3tr.connect(otherAccount).unpause());
expect(await b3tr.hasRole(await b3tr.PAUSER_ROLE(), owner.address)).to.eql(true);
await b3tr.connect(owner).pause();
expect(await b3tr.paused()).to.eql(true);
await b3tr.connect(owner).unpause();
expect(await b3tr.paused()).to.eql(false);
});
});
describe("Max supply", function () {
it("cannot be minted more than max supply", async function () {
const { b3tr, otherAccount, owner } = await getOrDeployContractInstances({ forceDeploy: true });
const operatorRole = await b3tr.MINTER_ROLE();
await b3tr.grantRole(operatorRole, owner);
await expect(b3tr.mint(otherAccount, ethers.parseEther("1000243155"))).to.be.reverted;
});
it("can be minted up to max supply", async function () {
const config = createLocalConfig();
const { b3tr, otherAccount, owner } = await getOrDeployContractInstances({ forceDeploy: false, config });
const operatorRole = await b3tr.MINTER_ROLE();
await b3tr.grantRole(operatorRole, owner);
await expect(b3tr.mint(otherAccount, ethers.parseEther("1000243154"))).not.to.be.reverted;
const balance = await b3tr.balanceOf(otherAccount);
expect(String(balance)).to.eql(ethers.parseEther("1000243154").toString());
});
});
describe("Mint", function () {
it("only accounts with minter role can mint", async function () {
const { b3tr, otherAccount, owner } = await getOrDeployContractInstances({ forceDeploy: true });
expect(await b3tr.totalSupply()).to.eql(0n);
await expect(b3tr.mint(otherAccount, ethers.parseEther("1"))).to.be.reverted;
expect(await b3tr.totalSupply()).to.eql(0n);
const operatorRole = await b3tr.MINTER_ROLE();
await b3tr.grantRole(operatorRole, owner);
await expect(b3tr.mint(otherAccount, ethers.parseEther("1"))).not.to.be.reverted;
expect(await b3tr.totalSupply()).to.eql(ethers.parseEther("1"));
const balance = await b3tr.balanceOf(otherAccount);
expect(String(balance)).to.eql(ethers.parseEther("1").toString());
});
it("Should not be able to mint if transfers are paused", async function () {
const { b3tr, otherAccount, owner } = await getOrDeployContractInstances({ forceDeploy: true });
const operatorRole = await b3tr.MINTER_ROLE();
await b3tr.grantRole(operatorRole, owner);
await b3tr.pause();
await catchRevert(b3tr.mint(otherAccount, ethers.parseEther("1")));
await b3tr.connect(owner).unpause();
await expect(b3tr.mint(otherAccount, ethers.parseEther("1"))).not.to.be.reverted;
});
});
describe("Token details", function () {
it("returns expected information", async function () {
const { b3tr } = await getOrDeployContractInstances({ forceDeploy: false });
const name = await b3tr.name();
const symbol = await b3tr.symbol();
const decimals = await b3tr.decimals();
const cap = await b3tr.cap();
const totalSupply = await b3tr.totalSupply();
const tokenDetails = await b3tr.tokenDetails();
expect(tokenDetails[0]).to.eql(name);
expect(tokenDetails[1]).to.eql(symbol);
expect(tokenDetails[2]).to.eql(decimals);
expect(tokenDetails[3]).to.eql(totalSupply);
expect(tokenDetails[4]).to.eql(cap);
});
});
});