mirror of
https://github.com/gitgig-io/ragnar.git
synced 2026-01-10 12:07:55 -05:00
739 lines
25 KiB
TypeScript
739 lines
25 KiB
TypeScript
import { expect } from "chai";
|
|
import { ethers } from "hardhat";
|
|
import { anyValue } from "@nomicfoundation/hardhat-chai-matchers/withArgs";
|
|
import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers";
|
|
import { createPointsTokenSignature } from "./helpers/signatureHelpers";
|
|
import { PointsTokenRegistry, PointsTokenFactory, BountiesRegistry } from "../typechain-types";
|
|
|
|
const TOTAL_SUPPLY = 20_000_000 * 100; // * 100 because of two decimals
|
|
const DECIMALS = 2;
|
|
const FEE = ethers.parseEther("0.002");
|
|
|
|
describe("PointsTokenFactory", () => {
|
|
async function bountiesFixture() {
|
|
const [
|
|
owner,
|
|
custodian,
|
|
finance,
|
|
notary,
|
|
issuer,
|
|
maintainer,
|
|
contributor,
|
|
contributor2,
|
|
contributor3,
|
|
] = await ethers.getSigners();
|
|
|
|
const IdentityFactory = await ethers.getContractFactory("Identity");
|
|
const identity = await IdentityFactory.deploy(
|
|
custodian.address,
|
|
notary.address,
|
|
"http://localhost:3000",
|
|
);
|
|
|
|
const ClaimValidatorFactory = await ethers.getContractFactory("StaticClaimValidator");
|
|
const claimValidator = await ClaimValidatorFactory.deploy(true);
|
|
|
|
const BountiesConfigFactory = await ethers.getContractFactory("BountiesConfig");
|
|
const bountiesConfig = await BountiesConfigFactory.deploy(
|
|
custodian.address,
|
|
notary.address,
|
|
await identity.getAddress(),
|
|
await claimValidator.getAddress(),
|
|
[]
|
|
);
|
|
|
|
const BountiesFactory = await ethers.getContractFactory("Bounties");
|
|
const bounties = await BountiesFactory.deploy(
|
|
await bountiesConfig.getAddress(),
|
|
custodian.address,
|
|
finance.address,
|
|
);
|
|
|
|
const BountiesRegistryFactory = await ethers.getContractFactory("BountiesRegistry");
|
|
const bountiesRegistry = await BountiesRegistryFactory.deploy(custodian.address);
|
|
bountiesRegistry.connect(custodian).addBountiesContract(await bounties.getAddress());
|
|
|
|
return {
|
|
owner,
|
|
custodian,
|
|
bounties,
|
|
bountiesConfig,
|
|
bountiesRegistry,
|
|
identity,
|
|
finance,
|
|
notary,
|
|
issuer,
|
|
maintainer,
|
|
contributor,
|
|
contributor2,
|
|
contributor3,
|
|
};
|
|
}
|
|
|
|
async function createBountiesRegistry(custodian: HardhatEthersSigner) {
|
|
const bountiesRegistryFactory = await ethers.getContractFactory("BountiesRegistry");
|
|
return await bountiesRegistryFactory.deploy(custodian);
|
|
}
|
|
|
|
async function createPointsTokenRegistry(custodian: HardhatEthersSigner) {
|
|
const pointsTokenRegistryFactory = await ethers.getContractFactory(
|
|
"PointsTokenRegistry",
|
|
);
|
|
const pointsTokenRegistry = await pointsTokenRegistryFactory.deploy(custodian);
|
|
|
|
return pointsTokenRegistry;
|
|
}
|
|
|
|
async function createPointsTokenFactory(
|
|
custodian: HardhatEthersSigner,
|
|
finance: HardhatEthersSigner,
|
|
notary: HardhatEthersSigner,
|
|
bountiesRegistry: BountiesRegistry,
|
|
tokenRegistry: PointsTokenRegistry,
|
|
) {
|
|
const pointsFactoryFactory = await ethers.getContractFactory(
|
|
"PointsTokenFactory",
|
|
);
|
|
const pointsFactory = await pointsFactoryFactory.deploy(
|
|
custodian,
|
|
finance,
|
|
notary,
|
|
await bountiesRegistry.getAddress(),
|
|
await tokenRegistry.getAddress(),
|
|
DECIMALS,
|
|
TOTAL_SUPPLY,
|
|
FEE,
|
|
);
|
|
|
|
return pointsFactory;
|
|
}
|
|
|
|
async function pointsTokenFactoryFixture() {
|
|
const fixtures = await bountiesFixture();
|
|
const { bountiesRegistry, custodian, finance, notary } = fixtures;
|
|
const tokenRegistry = await createPointsTokenRegistry(custodian);
|
|
const pointsFactory = await createPointsTokenFactory(
|
|
custodian,
|
|
finance,
|
|
notary,
|
|
bountiesRegistry,
|
|
tokenRegistry,
|
|
);
|
|
|
|
return { ...fixtures, tokenRegistry, pointsFactory };
|
|
}
|
|
|
|
async function pFixture() {
|
|
const fixtures = await pointsTokenFactoryFixture();
|
|
const { custodian, bountiesConfig, pointsFactory, tokenRegistry } = fixtures;
|
|
|
|
await pointsFactory.connect(custodian).addBountiesConfigContract(bountiesConfig);
|
|
await bountiesConfig
|
|
.connect(custodian)
|
|
.grantRole(await bountiesConfig.TRUSTED_CONTRACT_ROLE(), pointsFactory);
|
|
|
|
tokenRegistry
|
|
.connect(custodian)
|
|
.grantRole(
|
|
await tokenRegistry.TRUSTED_CONTRACT_ROLE(),
|
|
pointsFactory.getAddress(),
|
|
);
|
|
|
|
return fixtures;
|
|
}
|
|
|
|
const BASE_PARAMS = ["Test Points", "cpTST", "1", "GitGig"] as const;
|
|
|
|
async function pointsTokenParamsFixture(
|
|
pointsFactory: PointsTokenFactory,
|
|
issuer: HardhatEthersSigner,
|
|
notary: HardhatEthersSigner,
|
|
) {
|
|
const sigParams = [...BASE_PARAMS, issuer.address];
|
|
const signature = await createPointsTokenSignature(
|
|
pointsFactory,
|
|
sigParams,
|
|
notary,
|
|
);
|
|
return [...BASE_PARAMS, signature];
|
|
}
|
|
|
|
async function applyCreatePointsToken(
|
|
pointsFactory: PointsTokenFactory,
|
|
issuer: HardhatEthersSigner,
|
|
params: any[],
|
|
fee = FEE,
|
|
) {
|
|
const { createPointsToken: realCreate } = pointsFactory.connect(issuer);
|
|
return realCreate.apply(pointsFactory, [...params, { value: fee }] as any);
|
|
}
|
|
|
|
async function createPointsToken(
|
|
pointsFactory: PointsTokenFactory,
|
|
issuer: HardhatEthersSigner,
|
|
notary: HardhatEthersSigner,
|
|
fee = FEE,
|
|
) {
|
|
const params = await pointsTokenParamsFixture(
|
|
pointsFactory,
|
|
issuer,
|
|
notary,
|
|
);
|
|
return applyCreatePointsToken(pointsFactory, issuer, params, fee);
|
|
}
|
|
|
|
describe("Deployment", () => {
|
|
it("should be able to deploy points factory contract", async () => {
|
|
const { pointsFactory } = await pFixture();
|
|
expect(pointsFactory.getAddress()).to.be.a.string;
|
|
});
|
|
});
|
|
|
|
describe("Create Points Token", () => {
|
|
it("should be able to create a points token", async () => {
|
|
const { pointsFactory, issuer, notary } = await pFixture();
|
|
const tx = await createPointsToken(pointsFactory, issuer, notary);
|
|
expect(tx.hash).to.be.a.string;
|
|
});
|
|
|
|
it("should revert when paused", async () => {
|
|
const { pointsFactory, custodian, issuer, notary } = await pFixture();
|
|
await pointsFactory.connect(custodian).pause();
|
|
|
|
await expect(createPointsToken(pointsFactory, issuer, notary))
|
|
.to.revertedWithCustomError(pointsFactory, "EnforcedPause");
|
|
});
|
|
|
|
it("should revert if value is less than fee", async () => {
|
|
const { pointsFactory, issuer, notary } = await pFixture();
|
|
const value = FEE - ethers.toBigInt(1);
|
|
await expect(createPointsToken(pointsFactory, issuer, notary, value))
|
|
.to.be.revertedWithCustomError(pointsFactory, "WrongFeeAmount")
|
|
.withArgs(value);
|
|
});
|
|
|
|
it("should revert if value is more than fee", async () => {
|
|
const { pointsFactory, issuer, notary } = await pFixture();
|
|
const value = FEE + ethers.toBigInt(1);
|
|
await expect(createPointsToken(pointsFactory, issuer, notary, value))
|
|
.to.be.revertedWithCustomError(pointsFactory, "WrongFeeAmount")
|
|
.withArgs(value);
|
|
});
|
|
|
|
it("should register token as a supported token on bounties contract", async () => {
|
|
const { bountiesConfig, pointsFactory, issuer, notary, tokenRegistry } = await pFixture();
|
|
let tokenAddr = await tokenRegistry.getContract("1", "GitGig", "cpTST");
|
|
expect(tokenAddr).to.equal(ethers.ZeroAddress);
|
|
|
|
// when
|
|
await createPointsToken(pointsFactory, issuer, notary);
|
|
|
|
// then
|
|
tokenAddr = await tokenRegistry.getContract("1", "GitGig", "cpTST");
|
|
expect(tokenAddr).to.not.equal(ethers.ZeroAddress);
|
|
expect(await bountiesConfig.isSupportedToken(tokenAddr)).to.be.true;
|
|
});
|
|
|
|
it("should emit PointsTokenCreate event", async () => {
|
|
const { pointsFactory, issuer, notary } = await pFixture();
|
|
await expect(createPointsToken(pointsFactory, issuer, notary))
|
|
.to.emit(pointsFactory, "PointsTokenCreate")
|
|
.withArgs(
|
|
anyValue,
|
|
"Test Points",
|
|
"cpTST",
|
|
DECIMALS,
|
|
TOTAL_SUPPLY,
|
|
issuer.address,
|
|
"1",
|
|
"GitGig",
|
|
);
|
|
});
|
|
|
|
it("should revert when symbol does not start with p", async () => {
|
|
const { pointsFactory, issuer, notary } = await pFixture();
|
|
const params = ["Test Points", "TST", "1", "GitGig"];
|
|
const sigParams = [...params, issuer.address];
|
|
const signature = await createPointsTokenSignature(
|
|
pointsFactory,
|
|
sigParams,
|
|
notary,
|
|
);
|
|
|
|
await expect(
|
|
applyCreatePointsToken(pointsFactory, issuer, [...params, signature]),
|
|
)
|
|
.to.be.revertedWithCustomError(pointsFactory, "InvalidSymbol");
|
|
});
|
|
|
|
it("should revert with invalid signature", async () => {
|
|
const { pointsFactory, issuer } = await pFixture();
|
|
const params = ["Test Points", "cpTST", "1", "GitGig"];
|
|
const sigParams = [...params, issuer.address];
|
|
const wrongSignature = await createPointsTokenSignature(
|
|
pointsFactory,
|
|
sigParams,
|
|
issuer,
|
|
);
|
|
|
|
await expect(
|
|
applyCreatePointsToken(pointsFactory, issuer, [
|
|
...params,
|
|
wrongSignature,
|
|
]),
|
|
)
|
|
.to.be.revertedWithCustomError(pointsFactory, "InvalidSignature");
|
|
});
|
|
|
|
it("should register token in registry", async () => {
|
|
const { pointsFactory, issuer, notary, tokenRegistry } = await pFixture();
|
|
expect(
|
|
await tokenRegistry.getContract(
|
|
BASE_PARAMS[2],
|
|
BASE_PARAMS[3],
|
|
BASE_PARAMS[1],
|
|
),
|
|
)
|
|
.to.equal(ethers.ZeroAddress);
|
|
|
|
// when
|
|
await createPointsToken(pointsFactory, issuer, notary);
|
|
|
|
// then
|
|
expect(
|
|
await tokenRegistry.getContract(
|
|
BASE_PARAMS[2],
|
|
BASE_PARAMS[3],
|
|
BASE_PARAMS[1],
|
|
),
|
|
)
|
|
.to.not.equal(ethers.ZeroAddress);
|
|
});
|
|
|
|
it("should revert when owner already has symbol", async () => {
|
|
const { pointsFactory, issuer, notary, tokenRegistry } = await pFixture();
|
|
await createPointsToken(pointsFactory, issuer, notary);
|
|
|
|
await expect(createPointsToken(pointsFactory, issuer, notary))
|
|
.to.be.revertedWithCustomError(tokenRegistry, "SymbolAlreadyExists");
|
|
});
|
|
});
|
|
|
|
describe("Add Bounties Contract", () => {
|
|
it("should add contract to bountiesContracts", async () => {
|
|
const { bounties, custodian, pointsFactory } = await pointsTokenFactoryFixture();
|
|
const bountiesAddr = await bounties.getAddress();
|
|
|
|
// ensure not there
|
|
await expect(pointsFactory.bountiesConfigContracts(0)).to.be.reverted;
|
|
|
|
// when
|
|
await pointsFactory.connect(custodian).addBountiesConfigContract(bountiesAddr);
|
|
|
|
expect(await pointsFactory.bountiesConfigContracts(0)).to.equal(bountiesAddr);
|
|
});
|
|
|
|
it("should not allow contract to be added twice", async () => {
|
|
const { bounties, custodian, pointsFactory } = await pointsTokenFactoryFixture();
|
|
const bountiesAddr = await bounties.getAddress();
|
|
|
|
// ensure not there
|
|
await expect(pointsFactory.bountiesConfigContracts(0)).to.be.reverted;
|
|
|
|
// when
|
|
await pointsFactory.connect(custodian).addBountiesConfigContract(bountiesAddr);
|
|
|
|
// then
|
|
await expect(
|
|
pointsFactory.connect(custodian).addBountiesConfigContract(bountiesAddr),
|
|
)
|
|
.to.be.revertedWithCustomError(pointsFactory, "InvalidArgument");
|
|
});
|
|
|
|
it("should revert when called by non-custodian", async () => {
|
|
const { bounties, issuer, pointsFactory } = await pointsTokenFactoryFixture();
|
|
const bountiesAddr = await bounties.getAddress();
|
|
|
|
// ensure not there
|
|
await expect(pointsFactory.bountiesConfigContracts(0)).to.be.reverted;
|
|
|
|
// when
|
|
await expect(
|
|
pointsFactory.connect(issuer).addBountiesConfigContract(bountiesAddr),
|
|
)
|
|
.to.be.revertedWithCustomError(
|
|
pointsFactory,
|
|
"AccessControlUnauthorizedAccount",
|
|
);
|
|
|
|
// still not there
|
|
await expect(pointsFactory.bountiesConfigContracts(0)).to.be.reverted;
|
|
});
|
|
|
|
it("should emit ConfigChange event", async () => {
|
|
const { bounties, custodian, pointsFactory } = await pointsTokenFactoryFixture();
|
|
const bountiesAddr = await bounties.getAddress();
|
|
|
|
// when/then
|
|
await expect(
|
|
pointsFactory.connect(custodian).addBountiesConfigContract(bountiesAddr),
|
|
)
|
|
.to.emit(pointsFactory, "ConfigChange");
|
|
});
|
|
});
|
|
|
|
describe("Remove Bounties Config Contract", () => {
|
|
it("should remove contract from bountiesContracts", async () => {
|
|
const { bounties, custodian, pointsFactory } = await pointsTokenFactoryFixture();
|
|
const bountiesAddr = await bounties.getAddress();
|
|
|
|
await pointsFactory.connect(custodian).addBountiesConfigContract(bountiesAddr);
|
|
expect(await pointsFactory.bountiesConfigContracts(0)).to.equal(bountiesAddr);
|
|
|
|
// when
|
|
await pointsFactory.connect(custodian).removeBountiesConfigContract(
|
|
bountiesAddr,
|
|
);
|
|
|
|
await expect(pointsFactory.bountiesConfigContracts(0)).to.be.reverted;
|
|
});
|
|
|
|
it("should revert when contract not in bountiesContracts", async () => {
|
|
const { bounties, bountiesRegistry, custodian, finance, notary } = await bountiesFixture();
|
|
const tokenRegistry = await createPointsTokenRegistry(custodian);
|
|
const pointsFactory = await createPointsTokenFactory(
|
|
custodian,
|
|
finance,
|
|
notary,
|
|
bountiesRegistry,
|
|
tokenRegistry,
|
|
);
|
|
const bountiesAddr = await bounties.getAddress();
|
|
|
|
// when
|
|
await expect(
|
|
pointsFactory.connect(custodian).removeBountiesConfigContract(bountiesAddr),
|
|
)
|
|
.to.be.revertedWithCustomError(pointsFactory, "InvalidArgument");
|
|
});
|
|
|
|
it("should revert when called by non-custodian", async () => {
|
|
const { bounties, bountiesRegistry, custodian, finance, issuer, notary } =
|
|
await bountiesFixture();
|
|
const tokenRegistry = await createPointsTokenRegistry(custodian);
|
|
const pointsFactory = await createPointsTokenFactory(
|
|
custodian,
|
|
finance,
|
|
notary,
|
|
bountiesRegistry,
|
|
tokenRegistry,
|
|
);
|
|
const bountiesAddr = await bounties.getAddress();
|
|
|
|
await pointsFactory.connect(custodian).addBountiesConfigContract(bountiesAddr);
|
|
expect(await pointsFactory.bountiesConfigContracts(0)).to.equal(bountiesAddr);
|
|
|
|
// when
|
|
await expect(
|
|
pointsFactory.connect(issuer).removeBountiesConfigContract(bountiesAddr),
|
|
)
|
|
.to.be.revertedWithCustomError(
|
|
pointsFactory,
|
|
"AccessControlUnauthorizedAccount",
|
|
);
|
|
|
|
// then
|
|
expect(await pointsFactory.bountiesConfigContracts(0)).to.equal(bountiesAddr);
|
|
});
|
|
|
|
it("should emit ConfigChange event", async () => {
|
|
const { bounties, custodian, pointsFactory } = await pointsTokenFactoryFixture();
|
|
const bountiesAddr = await bounties.getAddress();
|
|
|
|
await pointsFactory.connect(custodian).addBountiesConfigContract(bountiesAddr);
|
|
expect(await pointsFactory.bountiesConfigContracts(0)).to.equal(bountiesAddr);
|
|
|
|
// when/then
|
|
await expect(
|
|
pointsFactory.connect(custodian).removeBountiesConfigContract(bountiesAddr),
|
|
)
|
|
.to.emit(pointsFactory, "ConfigChange");
|
|
});
|
|
});
|
|
|
|
describe("Set Decimals", () => {
|
|
it("should update decimals", async () => {
|
|
const { pointsFactory, custodian } = await pFixture();
|
|
await pointsFactory.connect(custodian).setDecimals(18);
|
|
expect(await pointsFactory.dec()).to.equal(18);
|
|
});
|
|
|
|
it("should revert with InvalidArgument when out of range", async () => {
|
|
const { pointsFactory, custodian } = await pFixture();
|
|
await expect(pointsFactory.connect(custodian).setDecimals(19))
|
|
.to.be.revertedWithCustomError(pointsFactory, "InvalidArgument");
|
|
expect(await pointsFactory.dec()).to.equal(DECIMALS); // default
|
|
});
|
|
|
|
it("should revert when called by non-custodian", async () => {
|
|
const { pointsFactory, issuer } = await pFixture();
|
|
await expect(pointsFactory.connect(issuer).setDecimals(18))
|
|
.to.be.revertedWithCustomError(
|
|
pointsFactory,
|
|
"AccessControlUnauthorizedAccount",
|
|
);
|
|
expect(await pointsFactory.dec()).to.equal(DECIMALS);
|
|
});
|
|
|
|
it("should emit ConfigChange event", async () => {
|
|
const { pointsFactory, custodian } = await pFixture();
|
|
await expect(pointsFactory.connect(custodian).setDecimals(18))
|
|
.to.emit(pointsFactory, "ConfigChange");
|
|
});
|
|
});
|
|
|
|
describe("Set Total Supply", () => {
|
|
it("should update total supply", async () => {
|
|
const { pointsFactory, custodian } = await pFixture();
|
|
await pointsFactory.connect(custodian).setTotalSupply(50_000);
|
|
expect(await pointsFactory.totalSupply()).to.equal(50_000);
|
|
});
|
|
|
|
it("should revert when called by non-custodian", async () => {
|
|
const { pointsFactory, issuer } = await pFixture();
|
|
await expect(pointsFactory.connect(issuer).setTotalSupply(100_000))
|
|
.to.be.revertedWithCustomError(
|
|
pointsFactory,
|
|
"AccessControlUnauthorizedAccount",
|
|
);
|
|
expect(await pointsFactory.totalSupply()).to.equal(TOTAL_SUPPLY);
|
|
});
|
|
|
|
it("should emit ConfigChange event", async () => {
|
|
const { pointsFactory, custodian } = await pFixture();
|
|
await expect(pointsFactory.connect(custodian).setTotalSupply(50_000))
|
|
.to.emit(pointsFactory, "ConfigChange");
|
|
});
|
|
});
|
|
|
|
describe("Set Fee", () => {
|
|
it("should update fee", async () => {
|
|
const { pointsFactory, custodian } = await pFixture();
|
|
await pointsFactory.connect(custodian).setFee(50_000);
|
|
expect(await pointsFactory.fee()).to.equal(50_000);
|
|
});
|
|
|
|
it("should revert when called by non-custodian", async () => {
|
|
const { pointsFactory, issuer } = await pFixture();
|
|
await expect(pointsFactory.connect(issuer).setFee(100_000))
|
|
.to.be.revertedWithCustomError(
|
|
pointsFactory,
|
|
"AccessControlUnauthorizedAccount",
|
|
);
|
|
expect(await pointsFactory.fee()).to.equal(FEE);
|
|
});
|
|
|
|
it("should emit ConfigChange event", async () => {
|
|
const { pointsFactory, custodian } = await pFixture();
|
|
await expect(pointsFactory.connect(custodian).setFee(50_000))
|
|
.to.emit(pointsFactory, "ConfigChange");
|
|
});
|
|
});
|
|
|
|
describe("Set Bounties Registry", () => {
|
|
it("should update registry", async () => {
|
|
const { custodian, pointsFactory } = await pointsTokenFactoryFixture();
|
|
const registry = await createBountiesRegistry(custodian);
|
|
const regAddr = await registry.getAddress();
|
|
|
|
await pointsFactory.connect(custodian).setBountiesRegistry(regAddr);
|
|
expect(await pointsFactory.bountiesRegistry()).to.equal(regAddr);
|
|
});
|
|
|
|
it("should revert when called by non-custodian", async () => {
|
|
const { custodian, pointsFactory, issuer } = await pFixture();
|
|
const oldRegAddr = await pointsFactory.bountiesRegistry();
|
|
const registry = await createBountiesRegistry(custodian);
|
|
const regAddr = await registry.getAddress();
|
|
await expect(pointsFactory.connect(issuer).setBountiesRegistry(regAddr))
|
|
.to.be.revertedWithCustomError(
|
|
pointsFactory,
|
|
"AccessControlUnauthorizedAccount",
|
|
);
|
|
expect(await pointsFactory.bountiesRegistry()).to.equal(oldRegAddr);
|
|
});
|
|
|
|
it("should emit ConfigChange event", async () => {
|
|
const { pointsFactory, custodian } = await pFixture();
|
|
const registry = await createBountiesRegistry(custodian);
|
|
const regAddr = await registry.getAddress();
|
|
|
|
await expect(pointsFactory.connect(custodian).setBountiesRegistry(regAddr))
|
|
.to.emit(pointsFactory, "ConfigChange");
|
|
});
|
|
});
|
|
|
|
describe("Set Token Registry", () => {
|
|
it("should update registry", async () => {
|
|
const { custodian, pointsFactory } = await pointsTokenFactoryFixture();
|
|
const registry = await createPointsTokenRegistry(custodian);
|
|
const regAddr = await registry.getAddress();
|
|
|
|
await pointsFactory.connect(custodian).setTokenRegistry(regAddr);
|
|
expect(await pointsFactory.tokenRegistry()).to.equal(regAddr);
|
|
});
|
|
|
|
it("should revert when called by non-custodian", async () => {
|
|
const { custodian, pointsFactory, issuer } = await pFixture();
|
|
const oldRegAddr = await pointsFactory.tokenRegistry();
|
|
const registry = await createPointsTokenRegistry(custodian);
|
|
await expect(pointsFactory.connect(issuer).setTokenRegistry(registry))
|
|
.to.be.revertedWithCustomError(
|
|
pointsFactory,
|
|
"AccessControlUnauthorizedAccount",
|
|
);
|
|
expect(await pointsFactory.tokenRegistry()).to.equal(oldRegAddr);
|
|
});
|
|
|
|
it("should emit ConfigChange event", async () => {
|
|
const { pointsFactory, custodian } = await pFixture();
|
|
const registry = await createPointsTokenRegistry(custodian);
|
|
const regAddr = await registry.getAddress();
|
|
|
|
await expect(pointsFactory.connect(custodian).setTokenRegistry(regAddr))
|
|
.to.emit(pointsFactory, "ConfigChange");
|
|
});
|
|
});
|
|
|
|
describe("Set Notary", () => {
|
|
it("should update notary", async () => {
|
|
const { pointsFactory, custodian, issuer } = await pFixture();
|
|
|
|
await pointsFactory.connect(custodian).setNotary(issuer.address);
|
|
expect(await pointsFactory.notary()).to.equal(issuer.address);
|
|
});
|
|
|
|
it("should revert when called by non-custodian", async () => {
|
|
const { pointsFactory, issuer, notary } = await pFixture();
|
|
await expect(pointsFactory.connect(issuer).setNotary(issuer.address))
|
|
.to.be.revertedWithCustomError(
|
|
pointsFactory,
|
|
"AccessControlUnauthorizedAccount",
|
|
);
|
|
expect(await pointsFactory.notary()).to.equal(notary.address);
|
|
});
|
|
|
|
it("should emit ConfigChange event", async () => {
|
|
const { pointsFactory, custodian, issuer } = await pFixture();
|
|
|
|
await expect(pointsFactory.connect(custodian).setNotary(issuer.address))
|
|
.to.emit(pointsFactory, "ConfigChange");
|
|
});
|
|
});
|
|
|
|
describe("Withdraw Fees", () => {
|
|
it("should withdraw all fees", async () => {
|
|
const { pointsFactory, issuer, notary, finance } = await pFixture();
|
|
await createPointsToken(pointsFactory, issuer, notary);
|
|
const finBal = await ethers.provider.getBalance(finance.address);
|
|
expect(await ethers.provider.getBalance(await pointsFactory.getAddress()))
|
|
.to.be.greaterThan(0);
|
|
|
|
// when
|
|
await pointsFactory.connect(finance).withdrawFees();
|
|
|
|
// then - ensure finance wallet increased value
|
|
expect(await ethers.provider.getBalance(await pointsFactory.getAddress()))
|
|
.to.equal(0);
|
|
expect(await ethers.provider.getBalance(finance.address)).to.be
|
|
.greaterThan(finBal);
|
|
});
|
|
|
|
it("should emit FeeWithdraw event", async () => {
|
|
const { pointsFactory, issuer, notary, finance } = await pFixture();
|
|
await createPointsToken(pointsFactory, issuer, notary);
|
|
|
|
// when/then
|
|
await expect(pointsFactory.connect(finance).withdrawFees())
|
|
.to.emit(pointsFactory, "FeeWithdraw")
|
|
.withArgs(finance.address, FEE);
|
|
});
|
|
|
|
it("should revert when called by non-finance", async () => {
|
|
const { custodian, pointsFactory, issuer, notary } = await pFixture();
|
|
await createPointsToken(pointsFactory, issuer, notary);
|
|
|
|
// when/then
|
|
await expect(pointsFactory.connect(custodian).withdrawFees())
|
|
.to.be.revertedWithCustomError(
|
|
pointsFactory,
|
|
"AccessControlUnauthorizedAccount",
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("Pause", () => {
|
|
it('should pause', async () => {
|
|
const { pointsFactory, custodian } = await pFixture();
|
|
|
|
// when
|
|
await pointsFactory.connect(custodian).pause();
|
|
|
|
// then
|
|
expect(await pointsFactory.paused()).to.be.true;
|
|
});
|
|
|
|
it('should emit Paused event', async () => {
|
|
const { pointsFactory, custodian } = await pFixture();
|
|
|
|
// when
|
|
await expect(pointsFactory.connect(custodian).pause())
|
|
.to.emit(pointsFactory, "Paused")
|
|
.withArgs(custodian.address);
|
|
});
|
|
|
|
|
|
it('should revert when called by non-custodian', async () => {
|
|
const { pointsFactory, finance } = await pFixture();
|
|
|
|
// when
|
|
await expect(pointsFactory.connect(finance).pause())
|
|
.to.be.revertedWithCustomError(pointsFactory, "AccessControlUnauthorizedAccount");
|
|
});
|
|
});
|
|
|
|
describe("Unpause", () => {
|
|
it('should unpause', async () => {
|
|
const { pointsFactory, custodian } = await pFixture();
|
|
await pointsFactory.connect(custodian).pause();
|
|
expect(await pointsFactory.paused()).to.be.true;
|
|
|
|
await pointsFactory.connect(custodian).unpause();
|
|
|
|
// then
|
|
expect(await pointsFactory.paused()).to.be.false;
|
|
});
|
|
|
|
it('should emit Unpaused event', async () => {
|
|
const { pointsFactory, custodian } = await pFixture();
|
|
await pointsFactory.connect(custodian).pause();
|
|
expect(await pointsFactory.paused()).to.be.true;
|
|
|
|
await expect(pointsFactory.connect(custodian).unpause())
|
|
.to.emit(pointsFactory, "Unpaused")
|
|
.withArgs(custodian.address);
|
|
});
|
|
|
|
it('should revert when called by non-custodian', async () => {
|
|
const { pointsFactory, custodian, finance } = await pFixture();
|
|
await pointsFactory.connect(custodian).pause();
|
|
expect(await pointsFactory.paused()).to.be.true;
|
|
|
|
// when
|
|
await expect(pointsFactory.connect(finance).unpause())
|
|
.to.be.revertedWithCustomError(pointsFactory, "AccessControlUnauthorizedAccount");
|
|
});
|
|
});
|
|
|
|
});
|