Skip to content

Commit

Permalink
Added MetaToken testing
Browse files Browse the repository at this point in the history
  • Loading branch information
alsco77 committed Jun 18, 2020
1 parent 39dbf26 commit d9029d1
Show file tree
Hide file tree
Showing 9 changed files with 701 additions and 41 deletions.
3 changes: 2 additions & 1 deletion contracts/shared/PausableModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import { Module } from "./Module.sol";
/**
* @title PausableModule
* @author Stability Labs Pty. Ltd.
* @dev Forked from openzeppelin-contracts/lifecycle/pausable
* @dev Forked from @openzeppelin/contracts/lifecycle/pausable
* Changes: `onlyGovernor` can pause
*/
contract PausableModule is Module {

Expand Down
4 changes: 2 additions & 2 deletions security/run-flattener.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
trap "exit" INT

# Run sol-merger on all contracts. The command needs all contracts
../node_modules/sol-merger/dist/bin/sol-merger.js "../contracts/**/*.sol" ../flat
../node_modules/sol-merger/dist/bin/sol-merger.js "../contracts/**/*.sol" ../_flat

MOCK='Mock'

# Loop each file present in `flat` folder
for filename in ../flat/*.sol; do
for filename in ../_flat/*.sol; do

name=${filename##*/}

Expand Down
4 changes: 2 additions & 2 deletions security/run-securify.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ mkdir -p ./securify/securify-report

# Loop each file present in `flat` folder and run slither on it
# Slither report of each file will be created under `slither-report` folder
for filename in ../flat/*.sol; do
for filename in ../_flat/*.sol; do

name=${filename##*/}
docker run -it -v $PWD/../flat:/share securify /share/$name 2>&1 | sed 's/\x1B\[[0-9;]\+[A-Za-z]//g' | tee ./securify/securify-report/$name.log
docker run -it -v $PWD/../_flat:/share securify /share/$name 2>&1 | sed 's/\x1B\[[0-9;]\+[A-Za-z]//g' | tee ./securify/securify-report/$name.log
done
2 changes: 1 addition & 1 deletion security/run-slither.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ mkdir -p ./slither/slither-report

# Loop each file present in `flat` folder and run slither on it
# Slither report of each file will be created under `slither-report` folder
for filename in ../flat/*.sol; do
for filename in ../_flat/*.sol; do

name=${filename##*/}
slither $filename --print human-summary 2>&1 | sed 's/\x1B\[[0-9;]\+[A-Za-z]//g' | tee ./slither/slither-report/$name.log
Expand Down
10 changes: 10 additions & 0 deletions test-utils/machines/standardAccounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,21 @@ export class StandardAccounts {
public all: Address[];

public default: Address;

public governor: Address;

public other: Address;

public dummy1: Address;

public dummy2: Address;

public dummy3: Address;

public dummy4: Address;

public fundManager: Address;

constructor(accounts: Address[]) {
this.all = accounts;

Expand All @@ -29,6 +36,9 @@ export class StandardAccounts {
this.dummy2,
this.dummy3,
this.dummy4,
this.fundManager,
] = accounts;
}
}

export default StandardAccounts;
194 changes: 194 additions & 0 deletions test/meta-token/TestMetaToken.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
import { expectRevert } from "@openzeppelin/test-helpers";

import { StandardAccounts, SystemMachine } from "@utils/machines";
import { simpleToExactAmount } from "@utils/math";
import { BN } from "@utils/tools";

import envSetup from "@utils/env_setup";
import * as t from "types/generated";
import shouldBehaveLikeModule from "../shared/behaviours/Module.behaviour";
import shouldBehaveLikeERC20 from "../shared/behaviours/ERC20.behaviour";
import shouldBehaveLikeERC20Burnable from "../shared/behaviours/ERC20Burnable.behaviour";

const MetaToken = artifacts.require("MetaToken");

const { expect } = envSetup.configure();

contract("MetaToken", async (accounts) => {
const ctx: {
module?: t.ModuleInstance;
token?: t.Erc20Instance;
burnableToken?: t.Erc20BurnableInstance;
} = {};
const sa = new StandardAccounts(accounts);
let systemMachine: SystemMachine;
let meta: t.MetaTokenInstance;

const redeployMeta = async (
nexusAddress = systemMachine.nexus.address,
fundRecipient = sa.fundManager,
): Promise<t.MetaTokenInstance> => {
return MetaToken.new(nexusAddress, fundRecipient);
};

before(async () => {
systemMachine = new SystemMachine(sa.all);
await systemMachine.initialiseMocks(false, false);
meta = await redeployMeta();
});

describe("verifying Module initialization", async () => {
before("reset contracts", async () => {
meta = await redeployMeta();
ctx.module = meta as t.ModuleInstance;
});

shouldBehaveLikeModule(ctx as Required<typeof ctx>, sa);

it("should properly store valid arguments", async () => {
expect(await meta.nexus()).eq(systemMachine.nexus.address);
});
});

describe("verifying ERC20 properties", async () => {
beforeEach("reset contracts", async () => {
meta = await redeployMeta();
ctx.token = meta as t.Erc20Instance;
ctx.burnableToken = meta as t.Erc20BurnableInstance;
});

shouldBehaveLikeERC20(
ctx as Required<typeof ctx>,
"ERC20",
simpleToExactAmount(100000000, 18),
sa.fundManager,
sa.dummy1,
sa.dummy2,
);

shouldBehaveLikeERC20Burnable(
ctx as Required<typeof ctx>,
sa.fundManager,
simpleToExactAmount(100000000, 18),
[sa.dummy1],
);

it("should properly store valid arguments", async () => {
expect(await meta.name()).eq("Meta");
expect(await meta.symbol()).eq("MTA");
expect(await meta.decimals()).bignumber.eq(new BN(18));
});
});

describe("custom ERC20Mintable", async () => {
beforeEach("reset contracts", async () => {
meta = await redeployMeta();
});
describe("managing minters", () => {
it("should not allow minters to add minters", async () => {
await expectRevert(
meta.addMinter(sa.dummy2, { from: sa.dummy1 }),
"Only governor can execute",
);
await expectRevert(
meta.addMinter(sa.dummy2, { from: sa.dummy2 }),
"Only governor can execute",
);
});
it("should allow the governor to add a minter", async () => {
expect(await meta.isMinter(sa.dummy1)).eq(false);
await meta.addMinter(sa.dummy1, { from: sa.governor });
expect(await meta.isMinter(sa.dummy1)).eq(true);
});
it("should not allow minters to remove minters", async () => {
// Add minter role
expect(await meta.isMinter(sa.dummy1)).eq(false);
await meta.addMinter(sa.dummy1, { from: sa.governor });
expect(await meta.isMinter(sa.dummy1)).eq(true);
// Minter or other cannot remove role
await expectRevert(
meta.removeMinter(sa.dummy1, { from: sa.dummy1 }),
"Only governor can execute",
);
await expectRevert(
meta.removeMinter(sa.dummy1, { from: sa.dummy2 }),
"Only governor can execute",
);
});
it("should allow the governor to remove a minter", async () => {
// Add minter role
expect(await meta.isMinter(sa.dummy1)).eq(false);
await meta.addMinter(sa.dummy1, { from: sa.governor });
expect(await meta.isMinter(sa.dummy1)).eq(true);
// Minter or other cannot remove role
await meta.removeMinter(sa.dummy1, { from: sa.governor });
expect(await meta.isMinter(sa.dummy1)).eq(false);
});
it("should allow a minter to renounce their minting ability", async () => {
expect(await meta.isMinter(sa.dummy1)).eq(false);
await meta.addMinter(sa.dummy1, { from: sa.governor });
expect(await meta.isMinter(sa.dummy1)).eq(true);
// Minter or other cannot remove role
await meta.renounceMinter({ from: sa.dummy1 });
expect(await meta.isMinter(sa.dummy1)).eq(false);
await expectRevert(
meta.renounceMinter({ from: sa.dummy1 }),
"Roles: account does not have role",
);
});
});
describe("minting Meta", () => {
it("should not allow a EOA to mint", async () => {
await expectRevert(
meta.mint(sa.dummy1, 1, { from: sa.default }),
"MinterRole: caller does not have the Minter role",
);
});
it("should not allow the governor to mint directly", async () => {
await expectRevert(
meta.mint(sa.dummy1, 1, { from: sa.governor }),
"MinterRole: caller does not have the Minter role",
);
});
it("should allow a minter to mint", async () => {
// Assign minting privs
await meta.addMinter(sa.dummy1, { from: sa.governor });
expect(await meta.isMinter(sa.dummy1)).eq(true);

// Get balance
const balBefore = await meta.balanceOf(sa.dummy1);

// Mint
await meta.mint(sa.dummy1, 1, { from: sa.dummy1 });

// Check output bal
const balAfter = await meta.balanceOf(sa.dummy1);
expect(balAfter).bignumber.eq(balBefore.add(new BN(1)));
});
it("should not allow a removed minter", async () => {
// Assign minting privs
await meta.addMinter(sa.dummy1, { from: sa.governor });
expect(await meta.isMinter(sa.dummy1)).eq(true);

// Get balance
const balBefore = await meta.balanceOf(sa.dummy1);

// Mint
await meta.mint(sa.dummy1, 1, { from: sa.dummy1 });

// Check output bal
const balAfter = await meta.balanceOf(sa.dummy1);
expect(balAfter).bignumber.eq(balBefore.add(new BN(1)));

// Remove minter privs
await meta.removeMinter(sa.dummy1, { from: sa.governor });
expect(await meta.isMinter(sa.dummy1)).eq(false);

await expectRevert(
meta.mint(sa.dummy1, 1, { from: sa.dummy1 }),
"MinterRole: caller does not have the Minter role",
);
});
});
});
});
35 changes: 0 additions & 35 deletions test/meta-token/TestMetaToken.spec.ts.park

This file was deleted.

0 comments on commit d9029d1

Please sign in to comment.