github.com/codingfuture/orig-energi3@v0.8.4/energi/contracts/test/BlacklistRegistryV1.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 MockProxy = artifacts.require('MockProxy');
    22  const MockContract = artifacts.require('MockContract');
    23  const BlacklistRegistryV1 = artifacts.require('BlacklistRegistryV1');
    24  const IBlacklistRegistry = artifacts.require('IBlacklistRegistry');
    25  const IProposal = artifacts.require('IProposal');
    26  const Gen2Migration = artifacts.require('Gen2Migration');
    27  const MasternodeRegistryV1 = artifacts.require('MasternodeRegistryV1');
    28  const MasternodeTokenV1 = artifacts.require('MasternodeTokenV1');
    29  const TreasuryV1 = artifacts.require('TreasuryV1');
    30  const StorageBlacklistRegistryV1 = artifacts.require('StorageBlacklistRegistryV1');
    31  const MockBlacklistProposalV1 = artifacts.require('MockBlacklistProposalV1');
    32  
    33  const common = require('./common');
    34  
    35  contract("BlacklistRegistryV1", async accounts => {
    36      const s = {
    37          artifacts,
    38          accounts,
    39          assert,
    40          it,
    41          web3,
    42      };
    43  
    44      before(async () => {
    45          s.registry_orig = await MasternodeRegistryV1.deployed();
    46          s.registry = await MasternodeRegistryV1.at(await s.registry_orig.proxy());
    47  
    48          s.mntoken_orig = await MasternodeTokenV1.deployed();
    49          s.mntoken = await MasternodeTokenV1.at(await s.mntoken_orig.proxy());
    50  
    51          s.treasury_orig = await TreasuryV1.deployed();
    52          s.treasury = await TreasuryV1.at(await s.treasury_orig.proxy());
    53          
    54          s.orig = await BlacklistRegistryV1.deployed();
    55          s.proxy = await MockProxy.at(await s.orig.proxy());
    56          s.mnregistry_proxy = await MockProxy.at(await s.orig.mnregistry_proxy());
    57          s.fake = await MockContract.new(s.proxy.address);
    58          s.proxy_abi = await BlacklistRegistryV1.at(s.proxy.address);
    59          s.token_abi = await IBlacklistRegistry.at(s.proxy.address);
    60          await s.proxy.setImpl(s.orig.address);
    61          s.storage = await StorageBlacklistRegistryV1.at(await s.proxy_abi.v1storage());
    62          s.compensation_fund = await s.orig.compensation_fund();
    63          Object.freeze(s);
    64      });
    65  
    66      after(async () => {
    67          const impl = await BlacklistRegistryV1.new(
    68              s.proxy.address, s.mnregistry_proxy.address,
    69              Gen2Migration.address, s.compensation_fund,
    70              accounts[9],
    71              { gas: "10000000" });
    72          await s.proxy.setImpl(impl.address);
    73      });
    74  
    75      describe('common pre', () => common.govPreTests(s) );
    76  
    77      //---
    78      describe('Primary', () => {
    79          const { fromAscii, toBN, toWei } = web3.utils;
    80          const enforce_fee = toBN(toWei('1000', 'ether'));
    81          const revoke_fee = toBN(toWei('100', 'ether'));
    82          const drain_fee = toBN(toWei('100', 'ether'));
    83  
    84          const collateral1 = toBN(toWei('50000', 'ether'));
    85          const owner1 = accounts[0];
    86          const masternode1 = accounts[9];
    87          const ip1 = toBN(0x12345678);
    88          const enode_common = '123456789012345678901234567890'
    89          const enode1 = [fromAscii(enode_common + '11'), fromAscii(enode_common + '11')];
    90  
    91          const target1 = accounts[1];
    92          const target2 = accounts[2];
    93  
    94          before(async () => {
    95              await s.mntoken.depositCollateral({
    96                  from: owner1,
    97                  value: collateral1,
    98              });
    99              await s.registry.announce(masternode1, ip1, enode1, {from: owner1});
   100          });
   101  
   102          after(async () => {
   103              await s.mntoken.withdrawCollateral(collateral1, {
   104                  from: owner1,
   105              });
   106          });
   107  
   108          it('should not be enforcelisted by default', async () => {
   109              expect(await s.token_abi.isBlacklisted(target1)).false;
   110          });
   111  
   112          it('should return EBI signer', async () => {
   113              expect(await s.token_abi.EBI_signer()).equal(accounts[3]);
   114          });
   115  
   116          it('should refuse propose() without proper fee', async () => {
   117              try {
   118                  await s.token_abi.propose(target1, { value: enforce_fee.sub(toBN(1)) });
   119                  assert.fail('It should fail');
   120              } catch (e) {
   121                  assert.match(e.message, /Invalid fee/);
   122              }
   123  
   124              try {
   125                  await s.token_abi.propose(target1, { value: enforce_fee.add(toBN(1)) });
   126                  assert.fail('It should fail');
   127              } catch (e) {
   128                  assert.match(e.message, /Invalid fee/);
   129              }
   130  
   131              try {
   132                  await s.token_abi.propose(target1, {
   133                      value: enforce_fee, from: await s.token_abi.EBI_signer()});
   134                  assert.fail('It should fail');
   135              } catch (e) {
   136                  assert.match(e.message, /Invalid fee/);
   137              }
   138          });
   139  
   140          it('should refuse proposeRevoke() without proper fee', async () => {
   141              try {
   142                  await s.token_abi.propose(target1, { value: revoke_fee.sub(toBN(1)) });
   143                  assert.fail('It should fail');
   144              } catch (e) {
   145                  assert.match(e.message, /Invalid fee/);
   146              }
   147  
   148              try {
   149                  await s.token_abi.propose(target1, { value: revoke_fee.add(toBN(1)) });
   150                  assert.fail('It should fail');
   151              } catch (e) {
   152                  assert.match(e.message, /Invalid fee/);
   153              }
   154  
   155              try {
   156                  await s.token_abi.propose(target1, {
   157                      value: revoke_fee, from: await s.token_abi.EBI_signer()});
   158                  assert.fail('It should fail');
   159              } catch (e) {
   160                  assert.match(e.message, /Invalid fee/);
   161              }
   162          });
   163  
   164  
   165          it('should refuse proposeDrain() without proper fee', async () => {
   166              try {
   167                  await s.token_abi.proposeDrain(target1, { value: drain_fee.sub(toBN(1)) });
   168                  assert.fail('It should fail');
   169              } catch (e) {
   170                  assert.match(e.message, /Invalid fee/);
   171              }
   172  
   173              try {
   174                  await s.token_abi.proposeDrain(target1, { value: drain_fee.add(toBN(1)) });
   175                  assert.fail('It should fail');
   176              } catch (e) {
   177                  assert.match(e.message, /Invalid fee/);
   178              }
   179  
   180              try {
   181                  await s.token_abi.proposeDrain(target1, {
   182                      value: drain_fee, from: await s.token_abi.EBI_signer()});
   183                  assert.fail('It should fail');
   184              } catch (e) {
   185                  assert.match(e.message, /Invalid fee/);
   186              }
   187          });
   188  
   189          it('should refuse proposeRevoke() on no enforce voting', async () => {
   190              try {
   191                  await s.token_abi.proposeRevoke(target1, { value: revoke_fee });
   192                  assert.fail('It should fail');
   193              } catch (e) {
   194                  assert.match(e.message, /No need \(1\)/);
   195              }
   196          });
   197  
   198          it('should enumerate*() empty', async () => {
   199              expect(await s.token_abi.enumerateAll()).length(0);
   200              expect(await s.token_abi.enumerateBlocked()).length(0);
   201          });
   202  
   203          it('should propose()', async () => {
   204              await s.token_abi.propose(target1, { value: enforce_fee });
   205  
   206              const evt = await s.orig.getPastEvents('BlacklistProposal', common.evt_last_block);
   207              expect(evt).lengthOf(1);
   208              common.stringifyBN(web3, evt[0].args);
   209              expect(evt[0].args).deep.include({
   210                  '0': target1,
   211                  '__length__': 2,
   212                  'target': target1,
   213              });
   214              expect(evt[0].args).include.keys('proposal');
   215  
   216              expect(await s.token_abi.isBlacklisted(target1)).false;
   217          });
   218  
   219          it('should enumerate*() one', async () => {
   220              const all = await s.token_abi.enumerateAll();
   221              const blocked = await s.token_abi.enumerateBlocked();
   222  
   223              expect(all).eql([target1]);
   224              expect(blocked).eql(['0x0000000000000000000000000000000000000000']);
   225          });
   226  
   227          it('should refuse propose() on active enforce voting', async () => {
   228              try {
   229                  await s.token_abi.propose(target1, { value: enforce_fee });
   230                  assert.fail('It should fail');
   231              } catch (e) {
   232                  assert.match(e.message, /Already active \(2\)/);
   233              }
   234          });
   235  
   236          it('should refuse proposeRevoke() on active enforce voting', async () => {
   237              try {
   238                  await s.token_abi.proposeRevoke(target1, { value: revoke_fee });
   239                  assert.fail('It should fail');
   240              } catch (e) {
   241                  assert.match(e.message, /Not applicable/);
   242              }
   243          });
   244  
   245          it('should refuse proposeRevoke() on rejected enforcement', async () => {
   246              const old_proposal = await IProposal.at((await s.token_abi.proposals(target1))['0']);
   247              await old_proposal.voteReject({from: owner1});
   248  
   249              try {
   250                  await s.token_abi.proposeRevoke(target1, { value: revoke_fee });
   251                  assert.fail('It should fail');
   252              } catch (e) {
   253                  assert.match(e.message, /No need \(2\)/);
   254              }
   255          });
   256  
   257          it('should propose() and collect rejected', async () => {
   258              await s.token_abi.propose(target1, { value: enforce_fee });
   259              expect(await s.treasury_orig.getPastEvents('Contribution', common.evt_last_block)).lengthOf(1);
   260              expect(await s.token_abi.isBlacklisted(target1)).false;
   261              expect(await s.token_abi.isBlacklisted(target2)).false;
   262          });
   263  
   264          it('should refuse collect() on lack of enforcement', async () => {
   265              try {
   266                  await s.token_abi.collect(target2);
   267                  assert.fail('It should fail');
   268              } catch (e) {
   269                  assert.match(e.message, /Nothing to collect/);
   270              }
   271          });
   272  
   273          it('should refuse collect() on enforce voting', async () => {
   274              try {
   275                  await s.token_abi.collect(target1);
   276                  assert.fail('It should fail');
   277              } catch (e) {
   278                  assert.match(e.message, /Enforce voting in progress/);
   279              }
   280          });
   281  
   282          it('should refuse propose() on enabled', async () => {
   283              const old_proposal = await IProposal.at((await s.token_abi.proposals(target1))['0']);
   284              await old_proposal.voteAccept({from: owner1});
   285              expect(await s.token_abi.isBlacklisted(target1)).true;
   286              expect(await s.token_abi.isBlacklisted(target2)).false;
   287  
   288              try {
   289                  await s.token_abi.propose(target1, { value: enforce_fee });
   290                  assert.fail('It should fail');
   291              } catch (e) {
   292                  assert.match(e.message, /Already active \(2\)/);
   293              }            
   294          });
   295  
   296          it('should refuse collect() on enforced', async () => {
   297              try {
   298                  await s.token_abi.collect(target1);
   299                  assert.fail('It should fail');
   300              } catch (e) {
   301                  assert.match(e.message, /No proposals ready to collect/);
   302              }
   303          });
   304  
   305          it('should proposeRevoke()', async () => {
   306              await s.token_abi.proposeRevoke(target1, { value: revoke_fee });
   307              expect(await s.token_abi.isBlacklisted(target1)).true;
   308              expect(await s.token_abi.isBlacklisted(target2)).false;
   309          });
   310  
   311          it('should refuse proposeRevoke() on active revoke voting', async () => {
   312              try {
   313                  await s.token_abi.proposeRevoke(target1, { value: revoke_fee });
   314                  assert.fail('It should fail');
   315              } catch (e) {
   316                  assert.match(e.message, /Already active/);
   317              }
   318          });
   319  
   320          it('should proposeRevoke() and collect rejected', async () => {
   321              const old_proposal = await IProposal.at((await s.token_abi.proposals(target1))['1']);
   322              await old_proposal.voteReject({from: owner1});
   323              await s.token_abi.proposeRevoke(target1, { value: revoke_fee });
   324              expect(await s.treasury_orig.getPastEvents('Contribution', common.evt_last_block)).lengthOf(1);
   325              expect(await s.token_abi.isBlacklisted(target1)).true;
   326              expect(await s.token_abi.isBlacklisted(target2)).false;
   327          });
   328  
   329          it('should refuse collect() on revoke voting', async () => {
   330              try {
   331                  await s.token_abi.collect(target1);
   332                  assert.fail('It should fail');
   333              } catch (e) {
   334                  assert.match(e.message, /Revoke voting in progress/);
   335              }
   336          });
   337  
   338          it('should collect() after rejected revocation', async () => {
   339              const old_proposal = await IProposal.at((await s.token_abi.proposals(target1))['1']);
   340              await old_proposal.voteReject({from: owner1});
   341              await s.token_abi.collect(target1);
   342              expect(await s.treasury_orig.getPastEvents('Contribution', common.evt_last_block)).lengthOf(1);
   343              expect(await s.token_abi.isBlacklisted(target1)).true;
   344              expect(await s.token_abi.isBlacklisted(target2)).false;
   345          });
   346  
   347          it('should collect() after approved revocation', async () => {
   348              await s.token_abi.proposeRevoke(target1, { value: revoke_fee });
   349              const old_proposal = await IProposal.at((await s.token_abi.proposals(target1))['1']);
   350              await old_proposal.voteAccept({from: owner1});
   351              await s.token_abi.collect(target1);
   352              expect(await s.treasury_orig.getPastEvents('Contribution', common.evt_last_block)).lengthOf(0);
   353              expect(await s.token_abi.isBlacklisted(target1)).false;
   354              expect(await s.token_abi.isBlacklisted(target2)).false;
   355  
   356          });
   357  
   358          it('should isObey() on accept', async () => {
   359              const proposal = await MockBlacklistProposalV1.new(s.mnregistry_proxy.address, accounts[0]);
   360              expect(await proposal.isObeyed()).false;
   361              await proposal.voteAccept();
   362              expect(await proposal.isObeyed()).true;
   363          });
   364  
   365          it('should isObeyed() on 2:1 weight over 10x votes', async () => {
   366              const proposal = await MockBlacklistProposalV1.new(s.mnregistry_proxy.address, accounts[0]);
   367              expect(await proposal.isObeyed()).false;
   368  
   369              const b = toBN(toWei('10000', 'ether'));
   370  
   371              // Must obey 10x
   372              await proposal.setWeights(toBN(20), toBN(9), toBN(10), toBN(30));
   373              expect(await proposal.isObeyed()).false;
   374  
   375              // 2>1
   376              await proposal.setWeights(toBN(20).mul(b), toBN(9).mul(b), toBN(1).mul(b), toBN(50).mul(b));
   377              expect(await proposal.isObeyed()).true;
   378              expect(await proposal.isAccepted()).false;
   379  
   380              // 2:1
   381              await proposal.setWeights(toBN(20).mul(b), toBN(10).mul(b), toBN(1).mul(b), toBN(50).mul(b));
   382              expect(await proposal.isObeyed()).false;
   383              expect(await proposal.isAccepted()).false;
   384  
   385              // < 10x
   386              await proposal.setWeights(toBN(7).mul(b), toBN(3).mul(b), toBN(1).mul(b), toBN(50).mul(b));
   387              expect(await proposal.isObeyed()).false;
   388              expect(await proposal.isAccepted()).false;
   389          });
   390  
   391          it('should proposeDrain() collect rejected', async () => {
   392              await s.token_abi.propose(target1, { value: enforce_fee });
   393              const enforce = await IProposal.at((await s.token_abi.proposals(target1))['0']);
   394              await enforce.voteAccept();
   395              await s.token_abi.proposeDrain(target1, { value: drain_fee });
   396              const drain = await IProposal.at((await s.token_abi.proposals(target1))['2']);
   397  
   398              expect(await s.token_abi.isDrainable(target1)).false;
   399              await drain.voteReject();
   400              expect(await s.token_abi.isDrainable(target1)).false;
   401  
   402              s.token_abi.collect(target1);
   403          });
   404  
   405          it('should proposeDrain()', async () => {
   406              await s.token_abi.proposeDrain(target1, { value: drain_fee });
   407              const drain = await IProposal.at((await s.token_abi.proposals(target1))['2']);
   408  
   409              expect(await s.token_abi.isDrainable(target1)).false;
   410              await drain.voteAccept();
   411              expect(await s.token_abi.isDrainable(target1)).true;
   412          });
   413  
   414          it('should refuse onDrain()', async () => {
   415              try {
   416                  await s.token_abi.onDrain(target1);
   417                  assert.fail('It should fail');
   418              } catch (e) {
   419                  assert.match(e.message, /Not consensus/);
   420              }
   421          });
   422  
   423          it('should accept drainMigration()', async () => {
   424              try {
   425                  await s.token_abi.drainMigration(0, target1);
   426                  assert.fail('It should fail');
   427              } catch (e) {
   428                  assert.match(e.message, /Invalid ID/);
   429              }
   430          });
   431  
   432          it('should refuse drainMigration()', async () => {
   433              try {
   434                  await s.token_abi.drainMigration(0, target2);
   435                  assert.fail('It should fail');
   436              } catch (e) {
   437                  assert.match(e.message, /Not drainable/);
   438              }
   439          });
   440      });
   441  
   442  
   443      //---
   444      describe('StorageBlacklistRegistryV1', async () => {
   445          it ('should refuse setRevoke() from outside', async () => {
   446              try {
   447                  await s.storage.setRevoke(s.fake.address, s.fake.address);
   448                  assert.fail('It must fail');
   449              } catch (e) {
   450                  assert.match(e.message, /Not owner/);
   451              }
   452          });
   453  
   454          it ('should refuse setEnforce() from outside', async () => {
   455              try {
   456                  await s.storage.setEnforce(s.fake.address, s.fake.address);
   457                  assert.fail('It must fail');
   458              } catch (e) {
   459                  assert.match(e.message, /Not owner/);
   460              }
   461          });
   462  
   463          it ('should refuse remove() from outside', async () => {
   464              try {
   465                  await s.storage.remove(s.fake.address);
   466                  assert.fail('It must fail');
   467              } catch (e) {
   468                  assert.match(e.message, /Not owner/);
   469              }
   470          });
   471      });
   472  
   473      //---
   474      describe('common post', () => common.govPostTests(s) );
   475  });
   476