github.com/codingfuture/orig-energi3@v0.8.4/energi/contracts/test/MasternodeTokenV2.spec.js (about) 1 // Copyright 2019 The Energi Core Authors 2 // This file is part of the Energi Core library. 3 // 4 // The Energi Core library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The Energi Core library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the Energi Core library. If not, see <http://www.gnu.org/licenses/>. 16 17 // Energi Governance system is the fundamental part of Energi Core. 18 19 'use strict'; 20 21 const MockProposal = artifacts.require('MockProposal'); 22 const MockProxy = artifacts.require('MockProxy'); 23 const MockContract = artifacts.require('MockContract'); 24 const MockSporkRegistry = artifacts.require('MockSporkRegistry'); 25 const MasternodeTokenV1 = artifacts.require('MasternodeTokenV1'); 26 const MasternodeTokenV2 = artifacts.require('MasternodeTokenV2'); 27 const IMasternodeToken = artifacts.require('IMasternodeToken'); 28 const StorageMasternodeTokenV1 = artifacts.require('StorageMasternodeTokenV1'); 29 30 const common = require('./common'); 31 32 contract("MasternodeTokenV2", async accounts => { 33 const s = { 34 artifacts, 35 accounts, 36 assert, 37 it, 38 web3, 39 storage: null, 40 }; 41 42 const COLLATERAL_01 = web3.utils.toWei('1000', 'ether'); 43 const COLLATERAL_1 = web3.utils.toWei('10000', 'ether'); 44 const COLLATERAL_2 = web3.utils.toWei('20000', 'ether'); 45 const COLLATERAL_3 = web3.utils.toWei('30000', 'ether'); 46 const COLLATERAL_4 = web3.utils.toWei('40000', 'ether'); 47 const COLLATERAL_7 = web3.utils.toWei('70000', 'ether'); 48 const COLLATERAL_9 = web3.utils.toWei('90000', 'ether'); 49 const COLLATERAL_10 = web3.utils.toWei('100000', 'ether'); 50 const COLLATERAL_13 = web3.utils.toWei('130000', 'ether'); 51 const check_age = async (age) => { 52 const bn = await web3.eth.getBlockNumber(); 53 expect(age.toString()).equal(bn.toString()); 54 }; 55 56 before(async () => { 57 s.orig = await MasternodeTokenV2.deployed(); 58 s.proxy = await MockProxy.at(await s.orig.proxy()); 59 s.registry_proxy = await MockProxy.at(await s.orig.registry_proxy()); 60 s.fake = await MockContract.new(s.proxy.address); 61 s.proxy_abi = await MasternodeTokenV2.at(s.proxy.address); 62 s.token_abi = await IMasternodeToken.at(s.proxy.address); 63 await s.proxy.setImpl(s.orig.address); 64 s.storage = await StorageMasternodeTokenV1.at(await s.proxy_abi.v1storage()); 65 Object.freeze(s); 66 }); 67 68 after(async () => { 69 const impl = await MasternodeTokenV2.new(s.proxy.address, s.registry_proxy.address); 70 await s.proxy.setImpl(impl.address); 71 72 await s.fake.testDrain(COLLATERAL_3, {from: accounts[1]}); 73 await s.fake.testDrain(COLLATERAL_1, {from: accounts[0]}); 74 }); 75 76 describe('common pre', () => common.govPreTests(s) ); 77 78 //--- 79 describe('ERC20', () => { 80 it('should emit Transfer in c-tor', async () => { 81 const tmp = await MasternodeTokenV2.new(s.proxy.address, s.registry_proxy.address); 82 83 const evt = await tmp.getPastEvents('Transfer', common.evt_last_block); 84 expect(evt).lengthOf(1); 85 expect(evt[0].args).deep.include({ 86 '__length__': 3, 87 'from': '0x0000000000000000000000000000000000000000', 88 'to': '0x0000000000000000000000000000000000000000', 89 'value': web3.utils.toBN('0'), 90 }); 91 }); 92 93 it('should support totalSupply()', async () => { 94 const res = await s.token_abi.totalSupply(); 95 assert.equal(res.valueOf(), 0); 96 }); 97 98 it('should support name()', async () => { 99 const res = await s.token_abi.name(); 100 assert.equal(res, "Masternode Collateral"); 101 }); 102 103 it('should support symbol()', async () => { 104 const res = await s.token_abi.symbol(); 105 assert.equal(res, "MNRG"); 106 }); 107 108 it('should support decimals()', async () => { 109 const res = await s.token_abi.decimals(); 110 assert.equal(res.valueOf(), 18); 111 }); 112 113 it('should support balanceOf()', async () => { 114 const res = await s.token_abi.balanceOf(s.fake.address); 115 assert.equal(res.valueOf(), 0); 116 }); 117 118 it('should support allowance()', async () => { 119 const res = await s.token_abi.allowance(s.fake.address, s.fake.address); 120 assert.equal(res.valueOf(), 0); 121 }); 122 123 it('should refuse transfer()', async () => { 124 try { 125 await s.token_abi.transfer(s.fake.address, '0'); 126 assert.fail("It must fail"); 127 } catch (e) { 128 assert.match(e.message, /Not allowed/); 129 } 130 }); 131 132 it('should refuse transferFrom()', async () => { 133 try { 134 await s.token_abi.transferFrom(s.fake.address, s.fake.address, '0'); 135 assert.fail("It must fail"); 136 } catch (e) { 137 assert.match(e.message, /Not allowed/); 138 } 139 }); 140 141 it('should refuse approve()', async () => { 142 try { 143 await s.token_abi.approve(s.fake.address, '0'); 144 assert.fail("It must fail"); 145 } catch (e) { 146 assert.match(e.message, /Not allowed/); 147 } 148 }); 149 }); 150 151 //--- 152 describe('Primary', () => { 153 it('should support balanceInfo()', async () => { 154 const res = await s.token_abi.balanceInfo(s.fake.address); 155 assert.equal(res['0'].valueOf(), 0); 156 }); 157 158 it('should allow depositCollateral()', async () => { 159 const { logs } = await s.token_abi.depositCollateral({ 160 from: accounts[0], 161 value: COLLATERAL_1, 162 }); 163 assert.equal(logs.length, 1); 164 const res = await s.token_abi.balanceInfo(accounts[0]); 165 assert.equal(res['0'].valueOf(), COLLATERAL_1); 166 await check_age(res['1']); 167 168 const res2 = await s.token_abi.balanceOf(accounts[0]); 169 assert.equal(res2.valueOf(), COLLATERAL_1); 170 171 const res3 = await s.token_abi.totalSupply(); 172 assert.equal(res3.valueOf(), COLLATERAL_1); 173 174 const evt = await s.orig.getPastEvents('Transfer', common.evt_last_block); 175 expect(evt).lengthOf(1); 176 expect(evt[0].args).deep.include({ 177 '__length__': 3, 178 'from': '0x0000000000000000000000000000000000000000', 179 'to': accounts[0], 180 'value': web3.utils.toBN(COLLATERAL_1), 181 }); 182 }); 183 184 it('should correctly reflect last block', async () => { 185 const res1 = await s.token_abi.balanceInfo(accounts[0]); 186 await common.moveTime(web3, 3600); 187 188 const res2 = await s.token_abi.balanceInfo(accounts[0]); 189 assert.equal(res2['0'].valueOf(), COLLATERAL_1); 190 assert.equal(res1['1'].toString(), res2['1'].toString()); 191 }); 192 193 it('should allow depositCollateral() direct', async () => { 194 const { logs } = await s.orig.depositCollateral({ 195 from: accounts[0], 196 value: COLLATERAL_2, 197 }); 198 assert.equal(logs.length, 1); 199 const res = await s.token_abi.balanceInfo(accounts[0]); 200 assert.equal(res['0'].valueOf(), COLLATERAL_3); 201 await check_age(res['1']); 202 203 const res2 = await s.token_abi.balanceOf(accounts[0]); 204 assert.equal(res2.valueOf(), COLLATERAL_3); 205 206 const total = await s.token_abi.totalSupply(); 207 208 assert.equal(total.valueOf(), COLLATERAL_3); 209 210 const evt = await s.orig.getPastEvents('Transfer', common.evt_last_block); 211 expect(evt).lengthOf(1); 212 expect(evt[0].args).deep.include({ 213 '__length__': 3, 214 'from': '0x0000000000000000000000000000000000000000', 215 'to': accounts[0], 216 'value': web3.utils.toBN(COLLATERAL_2), 217 }); 218 }); 219 220 it('should refuse depositCollateral() not a multiple of', async () => { 221 try { 222 await s.token_abi.depositCollateral({ 223 from: accounts[0], 224 value: web3.utils.toWei('10001', 'ether'), 225 }); 226 assert.fail("It must fail"); 227 } catch (e) { 228 assert.match(e.message, /Not a multiple/); 229 } 230 231 const evt = await s.orig.getPastEvents('Transfer', common.evt_last_block); 232 expect(evt).lengthOf(0); 233 }); 234 235 it('should allow depositCollateral() - max', async () => { 236 const { logs } = await s.token_abi.depositCollateral({ 237 from: accounts[0], 238 value: COLLATERAL_7, 239 }); 240 assert.equal(logs.length, 1); 241 const res = await s.token_abi.balanceInfo(accounts[0]); 242 assert.equal(res['0'].valueOf(), COLLATERAL_10); 243 await check_age(res['1']); 244 245 const res2 = await s.token_abi.balanceOf(accounts[0]); 246 assert.equal(res2.valueOf(), COLLATERAL_10); 247 248 const total = await s.token_abi.totalSupply(); 249 assert.equal(total.valueOf(), COLLATERAL_10); 250 }); 251 252 it('should refuse to depositCollateral() over max', async () => { 253 try { 254 await s.token_abi.depositCollateral({ 255 from: accounts[0], 256 value: web3.utils.toWei(COLLATERAL_1, 'ether'), 257 }); 258 assert.fail("It must fail"); 259 } catch (e) { 260 assert.match(e.message, /Too much/); 261 } 262 }); 263 264 it('should allow depositCollateral() another account', async () => { 265 const { logs } = await s.orig.depositCollateral({ 266 from: accounts[1], 267 value: COLLATERAL_3, 268 }); 269 assert.equal(logs.length, 1); 270 271 const res = await s.token_abi.balanceInfo(accounts[1]); 272 assert.equal(res['0'].valueOf(), COLLATERAL_3); 273 await check_age(res['1']); 274 275 const res2 = await s.token_abi.balanceOf(accounts[1]); 276 assert.equal(res2.valueOf(), COLLATERAL_3); 277 278 const total = await s.token_abi.totalSupply(); 279 assert.equal(total.valueOf(), COLLATERAL_13); 280 }); 281 282 it('should allow withdrawCollateral()', async () => { 283 const { logs } = await s.token_abi.withdrawCollateral(COLLATERAL_9, { 284 from: accounts[0], 285 }); 286 assert.equal(logs.length, 1); 287 const res = await s.token_abi.balanceInfo(accounts[0]); 288 assert.equal(res['0'].valueOf(), COLLATERAL_1); 289 await check_age(res['1']); 290 291 const total = await s.token_abi.totalSupply(); 292 assert.equal(total.valueOf(), COLLATERAL_4); 293 294 const evt = await s.orig.getPastEvents('Transfer', common.evt_last_block); 295 expect(evt).lengthOf(1); 296 expect(evt[0].args).deep.include({ 297 '__length__': 3, 298 'from': accounts[0], 299 'to': '0x0000000000000000000000000000000000000000', 300 'value': web3.utils.toBN(COLLATERAL_9), 301 }); 302 }); 303 304 it('should refuse withdrawCollateral() over balance', async () => { 305 try { 306 await s.token_abi.withdrawCollateral(COLLATERAL_2, { 307 from: accounts[0], 308 }); 309 assert.fail("It must fail"); 310 } catch (e) { 311 assert.match(e.message, /Not enough/); 312 } 313 314 const evt = await s.orig.getPastEvents('Transfer', common.evt_last_block); 315 expect(evt).lengthOf(0); 316 }); 317 318 it('should refuse setBalance() on s.storage', async () => { 319 try { 320 await s.storage.setBalance(s.fake.address, COLLATERAL_1, COLLATERAL_1); 321 assert.fail("It must fail"); 322 } catch (e) { 323 assert.match(e.message, /Not owner/); 324 } 325 }); 326 327 it('should allow depositCollateral() - V2 min', async () => { 328 const { logs } = await s.token_abi.depositCollateral({ 329 from: accounts[2], 330 value: COLLATERAL_01, 331 }); 332 assert.equal(logs.length, 1); 333 const res = await s.token_abi.balanceInfo(accounts[2]); 334 assert.equal(res['0'].valueOf(), COLLATERAL_01); 335 await check_age(res['1']); 336 }); 337 338 it('should migrate from V1', async () => { 339 // Spork registry 340 const registry_proxy = await MockProxy.new(); 341 const registry = await MockSporkRegistry.new(registry_proxy.address); 342 await registry_proxy.setImpl(registry.address); 343 344 // MNToken proxy 345 const mn_proxy = await MockProxy.new(); 346 const imn = await IMasternodeToken.at(mn_proxy.address); 347 348 const impl1 = await MasternodeTokenV1.new(mn_proxy.address, registry_proxy.address); 349 const impl2 = await MasternodeTokenV2.new(mn_proxy.address, registry_proxy.address); 350 await mn_proxy.setImpl(impl1.address); 351 352 // Deposit before migration 353 await imn.depositCollateral({ 354 from: accounts[0], 355 value: COLLATERAL_1, 356 }); 357 358 // Upgrade 359 const { logs } = await mn_proxy.proposeUpgrade(impl2.address, 0); 360 s.assert.equal(logs.length, 1); 361 362 const proposal = await MockProposal.at(logs[0].args['1']); 363 364 await proposal.setAccepted(); 365 await mn_proxy.upgrade(proposal.address); 366 367 const res = await impl2.balanceInfo(accounts[0]); 368 assert.equal(res['0'].valueOf(), COLLATERAL_1); 369 370 await imn.withdrawCollateral(COLLATERAL_1, { 371 from: accounts[0], 372 }); 373 374 const res2 = await impl2.balanceInfo(accounts[0]); 375 assert.equal(res2['0'].valueOf(), 0); 376 }); 377 }); 378 379 //--- 380 describe('common post', () => common.govPostTests(s) ); 381 });