Skip to content

Commit 0f2c565

Browse files
authored
Common token (#753)
* firstr version * fix * tests * split long controller tests
1 parent fd9e726 commit 0f2c565

File tree

3 files changed

+258
-4
lines changed

3 files changed

+258
-4
lines changed

contracts/misc/CommonToken.sol

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
pragma solidity ^0.5.17;
2+
3+
import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC20/StandaloneERC20.sol";
4+
import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC20/IERC20.sol";
5+
6+
7+
/**
8+
* @title CommonToken, base on zeppelin contract.
9+
* @dev ERC20 compatible token. It is a mintable, burnable token(onlyMinter)
10+
*/
11+
contract CommonToken is StandaloneERC20 {
12+
13+
/**
14+
* @dev Destroys `amount` tokens from the caller.
15+
*
16+
* See {ERC20-_burn}.
17+
*/
18+
function burn(address _account, uint256 _amount) public onlyMinter {
19+
_burn(_account, _amount);
20+
}
21+
}

test/commontoken.js

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
const helpers = require('./helpers');
2+
3+
const CommonToken = artifacts.require("./CommonToken.sol");
4+
var token;
5+
contract('CommonToken', accounts => {
6+
const testTokenName = "CommonToken";
7+
const testTokenSymbol = "CMN";
8+
beforeEach( async function() {
9+
token = await CommonToken.new();
10+
await token.initialize(testTokenName,testTokenSymbol,18,[accounts[0]],[accounts[0]]);
11+
});
12+
it("should put 0 Coins in the first account", async () => {
13+
14+
let balance = await token.balanceOf.call(accounts[0]);
15+
assert.equal(balance.valueOf(), 0);
16+
});
17+
18+
it("should be owned by its creator", async () => {
19+
20+
assert.equal(await token.isMinter(accounts[0]), true);
21+
});
22+
23+
it("should mint tokens to owner account", async () => {
24+
await helpers.etherForEveryone(accounts);
25+
26+
let owner, totalSupply, userSupply;
27+
28+
totalSupply = await token.totalSupply();
29+
owner = accounts[0];
30+
userSupply = await token.balanceOf(owner);
31+
assert.equal(totalSupply, 0);
32+
assert.equal(userSupply, 0);
33+
34+
await token.mint(owner, 1000);
35+
totalSupply = await token.totalSupply();
36+
userSupply = await token.balanceOf(owner);
37+
assert.equal(totalSupply, 1000);
38+
assert.equal(userSupply, 1000);
39+
40+
await token.mint(accounts[2], 1300);
41+
totalSupply = await token.totalSupply();
42+
userSupply = await token.balanceOf(accounts[2]);
43+
assert.equal(totalSupply, 2300);
44+
assert.equal(userSupply, 1300);
45+
46+
});
47+
48+
it("should allow minting tokens only by owner", async () => {
49+
await helpers.etherForEveryone(accounts);
50+
51+
let owner = accounts[0];
52+
let totalSupply = await token.totalSupply();
53+
54+
// calling 'mint' as a non-owner throws an error
55+
try {
56+
await token.mint(owner, 1000, { 'from': accounts[1] });
57+
throw 'an error';
58+
} catch (error) {
59+
helpers.assertVMException(error);
60+
}
61+
62+
// and so the supply of tokens should remain unchanged
63+
let newSupply = await token.totalSupply();
64+
assert.equal(totalSupply.toNumber(), newSupply.toNumber());
65+
});
66+
67+
it("log the Transfer event on mint", async () => {
68+
69+
70+
const tx = await token.mint(accounts[1], 1000, { from: accounts[0] });
71+
72+
assert.equal(tx.logs.length, 1);
73+
assert.equal(tx.logs[0].event, "Transfer");
74+
assert.equal(tx.logs[0].args.to, accounts[1]);
75+
assert.equal(tx.logs[0].args.value.toNumber(), 1000);
76+
});
77+
78+
it("mint should be reflected in totalSupply", async () => {
79+
80+
81+
await token.mint(accounts[1], 1000, { from: accounts[0] });
82+
let amount = await token.totalSupply();
83+
84+
assert.equal(amount, 1000);
85+
86+
await token.mint(accounts[2], 500, { from: accounts[0] });
87+
amount = await token.totalSupply();
88+
89+
assert.equal(amount.toNumber(), 1500);
90+
});
91+
92+
it("mint should be reflected in balances", async () => {
93+
94+
95+
await token.mint(accounts[1], 1000, { from: accounts[0] });
96+
97+
const amount = await token.balanceOf(accounts[1]);
98+
99+
assert.equal(amount.toNumber(), 1000);
100+
});
101+
102+
it("totalSupply is 0 on init", async () => {
103+
104+
105+
const totalSupply = await token.totalSupply();
106+
107+
assert.equal(totalSupply.toNumber(), 0);
108+
});
109+
110+
it("burn", async () => {
111+
112+
await token.mint(accounts[1], 1000, { from: accounts[0] });
113+
114+
var amount = await token.balanceOf(accounts[1]);
115+
116+
assert.equal(amount.toNumber(), 1000);
117+
118+
await token.burn(accounts[1] ,100);
119+
120+
amount = await token.balanceOf(accounts[1]);
121+
122+
assert.equal(amount.toNumber(), 900);
123+
124+
const totalSupply = await token.totalSupply();
125+
126+
assert.equal(totalSupply.toNumber(), 900);
127+
});
128+
129+
130+
describe('onlyOwner', () => {
131+
it('mint by owner', async () => {
132+
try {
133+
await token.mint(accounts[1], 10, { from: accounts[0] });
134+
} catch (ex) {
135+
assert(false, 'owner could not mint');
136+
}
137+
});
138+
139+
it('mint by not owner', async () => {
140+
141+
try {
142+
await token.mint(accounts[1], 10, { from: accounts[1] });
143+
} catch (ex) {
144+
return;
145+
}
146+
147+
assert(false, 'non-owner was able to mint');
148+
});
149+
150+
it('burn by owner', async () => {
151+
await token.mint(accounts[1], 10);
152+
try {
153+
await token.burn(accounts[1], 10, { from: accounts[0] });
154+
} catch (ex) {
155+
assert(false, 'owner could not mint');
156+
}
157+
});
158+
159+
it('burn by not owner', async () => {
160+
await token.mint(accounts[1], 10, { from: accounts[0] });
161+
try {
162+
await token.burn(accounts[1], 10, { from: accounts[1] });
163+
} catch (ex) {
164+
return;
165+
}
166+
167+
assert(false, 'non-owner was able to mint');
168+
});
169+
});
170+
});

test/controller.js

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,37 @@ contract('Controller', accounts => {
105105
assert.equal(tx.logs[0].event, "RegisterScheme");
106106
});
107107

108-
it("register schemes - check permissions for register new scheme", async () => {
108+
it("register schemes - check permissions for register new scheme 0-7", async () => {
109109
// Check scheme has at least the permissions it is changing, and at least the current permissions.
110110
var i,j;
111111
// controller;
112-
for(j = 0; j <= 15; j++ ){
112+
for(j = 0; j <= 7; j++ ){
113+
//registered scheme has already permission to register(2)
114+
controller = await setup(accounts,'0x'+uint32.toHex(j|2));
115+
var register;
116+
for(i = 0; i <= 15; i++ ){
117+
register = true;
118+
try {
119+
await controller.registerScheme(accounts[1],'0x'+uint32.toHex(i));
120+
} catch (ex) {
121+
//registered scheme has already permission to register(2) and is register(1).
122+
assert.notEqual(i&(~(j|3),0));
123+
register = false;
124+
}
125+
if (register){
126+
await controller.unregisterScheme(accounts[1]);
127+
register= false;
128+
}
129+
}
130+
}
131+
});
132+
133+
134+
it("register schemes - check permissions for register new scheme 7-15", async () => {
135+
// Check scheme has at least the permissions it is changing, and at least the current permissions.
136+
var i,j;
137+
// controller;
138+
for(j = 7; j <= 15; j++ ){
113139
//registered scheme has already permission to register(2)
114140
controller = await setup(accounts,'0x'+uint32.toHex(j|2));
115141
var register;
@@ -158,7 +184,7 @@ contract('Controller', accounts => {
158184
assert.equal(tx.logs.length, 0);
159185
});
160186

161-
it("unregister schemes - check permissions unregister scheme", async () => {
187+
it("unregister schemes - check permissions unregister scheme 0-7", async () => {
162188
// Check scheme has at least the permissions it is changing, and at least the current permissions.
163189
//1. setup
164190
controller = await setup(accounts);
@@ -167,7 +193,7 @@ contract('Controller', accounts => {
167193
var tx;
168194
var registeredScheme = accounts[1];
169195
var unregisteredScheme = accounts[2];
170-
for(i = 0; i <= 15; i++ ){
196+
for(i = 0; i <= 7; i++ ){
171197
//registered scheme has already permission to register(2)
172198
tx = await controller.registerScheme(registeredScheme,'0x'+uint32.toHex(i|3));
173199
assert.equal(tx.logs.length, 1);
@@ -195,6 +221,43 @@ contract('Controller', accounts => {
195221
}
196222
});
197223

224+
it("unregister schemes - check permissions unregister scheme 7-15", async () => {
225+
// Check scheme has at least the permissions it is changing, and at least the current permissions.
226+
//1. setup
227+
controller = await setup(accounts);
228+
//2. account[0] register schemes ,on account[1] with variables permissions which could unregister other schemes.
229+
var i,j;
230+
var tx;
231+
var registeredScheme = accounts[1];
232+
var unregisteredScheme = accounts[2];
233+
for(i = 7; i <= 15; i++ ){
234+
//registered scheme has already permission to register(2)
235+
tx = await controller.registerScheme(registeredScheme,'0x'+uint32.toHex(i|3));
236+
assert.equal(tx.logs.length, 1);
237+
assert.equal(tx.logs[0].event, "RegisterScheme");
238+
for(j = 0; j <= 15; j++ ){
239+
tx = await controller.registerScheme(unregisteredScheme,'0x'+uint32.toHex(j));
240+
assert.equal(tx.logs.length, 1);
241+
assert.equal(tx.logs[0].event, "RegisterScheme");
242+
//try to unregisterScheme
243+
if (j&(~(i|3))) {
244+
//unregister should fail
245+
try {
246+
await controller.unregisterScheme(unregisteredScheme,{ from: registeredScheme });
247+
assert(false, "scheme with permission " +uint32.toHex(i|3)+ " should not be able to unregister scheme with permission"+uint32.toHex(j));
248+
} catch (ex) {
249+
helpers.assertVMException(ex);
250+
}
251+
}else{
252+
//unregister should succeed
253+
tx = await controller.unregisterScheme(unregisteredScheme,{ from: registeredScheme });
254+
assert.equal(tx.logs.length, 1);
255+
assert.equal(tx.logs[0].event, "UnregisterScheme");
256+
}
257+
}
258+
}
259+
});
260+
198261
it("unregister self", async () => {
199262
var tx;
200263
controller = await setup(accounts,"0x00000000");

0 commit comments

Comments
 (0)