Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion contracts/interfaces/IMemberRoles.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ pragma experimental ABIEncoderV2;

interface IMemberRoles {

enum Role {UnAssigned, AdvisoryBoard, Member, Owner}
enum Role {Unassigned, AdvisoryBoard, Member, Owner}

function join(address _userAddress, uint nonce, bytes calldata signature) external payable;

Expand Down
4 changes: 2 additions & 2 deletions contracts/mocks/MasterMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import "../modules/capital/Pool.sol";
contract MasterMock {

enum Role {
NonMember,
Unassigned,
AdvisoryBoard,
Member,
AdvisoryBord,
Owner
}

Expand Down
5 changes: 4 additions & 1 deletion contracts/mocks/MemberRoles/MRMockCover.sol
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
// SPDX-License-Identifier: GPL-3.0-only

import "../../interfaces/IStakingPool.sol";
import "../../interfaces/IMemberRoles.sol";
import "../../interfaces/ICoverNFT.sol";

pragma solidity ^0.8.16;

contract MRMockCover {
ICoverNFT immutable public coverNFT;
IMemberRoles immutable public memberRoles;
address[] public stakingPools;

constructor(address coverNFTAddress) {
constructor(address coverNFTAddress, address memberRolesAddress) {
coverNFT = ICoverNFT(coverNFTAddress);
memberRoles = IMemberRoles(memberRolesAddress);
}

function transferCovers(address from, address to, uint256[] calldata coverIds) external {
Expand Down
11 changes: 11 additions & 0 deletions contracts/mocks/MemberRoles/MRMockQuotationData.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// SPDX-License-Identifier: GPL-3.0-only

pragma solidity ^0.8.16;

contract MRMockQuotationData {
address public kycAuthAddress;

function setKycAuthAddress(address _add) external {
kycAuthAddress = _add;
}
}
2 changes: 1 addition & 1 deletion contracts/mocks/MemberRolesMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import "../interfaces/IMemberRoles.sol";

contract MemberRolesMock {

enum Role { UnAssigned, AdvisoryBoard, Member, Owner }
enum Role { Unassigned, AdvisoryBoard, Member, Owner }

mapping(address => Role) roles;

Expand Down
2 changes: 1 addition & 1 deletion contracts/modules/governance/MemberRoles.sol
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ contract MemberRoles is IMemberRoles, Governed, MasterAwareV2 {
address _memberAddress,
uint _roleId
) public override view returns (bool) {//solhint-disable-line
if (_roleId == uint(Role.UnAssigned))
if (_roleId == uint(Role.Unassigned))
return true;
else
if (memberRoleData[_roleId].memberActive[_memberAddress]) //solhint-disable-line
Expand Down
2 changes: 1 addition & 1 deletion contracts/modules/governance/VotePower.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ contract VotePower {

INXMMaster immutable public master;

enum Role {UnAssigned, AdvisoryBoard, Member}
enum Role {Unassigned, AdvisoryBoard, Member}

constructor(INXMMaster _master) {
master = _master;
Expand Down
16 changes: 15 additions & 1 deletion lib/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const NXMasterOwnerParamType = {
};

const Role = {
NonMember: 0,
Unassigned: 0,
AdvisoryBoard: 1,
Member: 2,
Owner: 3,
Expand Down Expand Up @@ -83,6 +83,19 @@ const ContractTypes = {
Proxy: 2,
};

const InternalContractsIDs = {
TC: 0, // TokenController.sol
P1: 1, // Pool.sol
MR: 2, // MemberRoles.sol
MC: 3, // MCR.sol
CO: 4, // Cover.sol
AS: 5, // Assessment.sol
TK: 6, // NXMToken.sol
PS: 7, // LegacyPooledStaking.sol
GV: 8, // Governance.sol
IC: 9, // IndividualClaims.sol
};

const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';

module.exports = {
Expand All @@ -95,6 +108,7 @@ module.exports = {
Role,
MCRUintParamType,
ContractTypes,
InternalContractsIDs,
NXMasterOwnerParamType,
PoolAsset,
ZERO_ADDRESS,
Expand Down
3 changes: 2 additions & 1 deletion test/unit/Assessment/castVotes.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const { ethers } = require('hardhat');
const { expect } = require('chai');
const { setTime } = require('./helpers');
const { Role } = require('../../../lib/constants');

const { parseEther } = ethers.utils;
const daysToSeconds = days => days * 24 * 60 * 60;
Expand Down Expand Up @@ -474,7 +475,7 @@ describe('castVotes', function () {

// Add AB and nonMember accounts as new members
for (const member of this.accounts.advisoryBoardMembers) {
await memberRoles.enrollMember(member.address, 2);
await memberRoles.enrollMember(member.address, Role.Member);
await nxm.mint(member.address, parseEther('10000'));
await nxm.connect(member).approve(tokenController.address, parseEther('10000'));
}
Expand Down
5 changes: 3 additions & 2 deletions test/unit/Assessment/setup.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const { ethers } = require('hardhat');
const { hex } = require('../../../lib/helpers');
const { getAccounts } = require('../../utils/accounts');
const { Role } = require('../../../lib/constants');
const { parseEther } = ethers.utils;

async function setup() {
Expand Down Expand Up @@ -65,8 +66,8 @@ async function setup() {
const accounts = await getAccounts();
await master.enrollGovernance(accounts.governanceContracts[0].address);
for (const member of accounts.members) {
await master.enrollMember(member.address, 1); // Uses a different role value than IMemberRoles
await memberRoles.enrollMember(member.address, 2); // Uses the actual member role value
await master.enrollMember(member.address, Role.Member);
await memberRoles.enrollMember(member.address, Role.Member);
await nxm.mint(member.address, parseEther('10000'));
await nxm.connect(member).approve(tokenController.address, parseEther('10000'));
}
Expand Down
3 changes: 2 additions & 1 deletion test/unit/Assessment/withdrawRewards.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const { expect } = require('chai');

const { setNextBlockBaseFee } = require('../utils').evm;
const { setTime, finalizePoll, generateRewards } = require('./helpers');
const { Role } = require('../../../lib/constants');

const { parseEther } = ethers.utils;
const daysToSeconds = days => days * 24 * 60 * 60;
Expand Down Expand Up @@ -284,7 +285,7 @@ describe('withdrawRewards', function () {

// Add AB accounts as new members
for (const member of this.accounts.advisoryBoardMembers) {
await memberRoles.enrollMember(member.address, 2);
await memberRoles.enrollMember(member.address, Role.Member);
await nxm.mint(member.address, parseEther('10000'));
await nxm.connect(member).approve(tokenController.address, parseEther('10000'));
}
Expand Down
35 changes: 35 additions & 0 deletions test/unit/MemberRoles/changeAuthorized.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
const { Role } = require('../utils').constants;
const { expect } = require('chai');

describe('changeAuthorized', function () {
it('should change authorized address for the role', async function () {
const { memberRoles } = this.contracts;
const {
advisoryBoardMembers: [advisoryBoardMember],
governanceContracts,
} = this.accounts;

const authorizedAddressBefore = await memberRoles.authorized(Role.AdvisoryBoard);
await memberRoles.connect(governanceContracts[0]).changeAuthorized(Role.AdvisoryBoard, advisoryBoardMember.address);
const authorizedAddressAfter = await memberRoles.authorized(Role.AdvisoryBoard);

expect(authorizedAddressBefore).not.to.be.equal(advisoryBoardMember.address);
expect(authorizedAddressAfter).to.be.equal(advisoryBoardMember.address);

await expect(
memberRoles.connect(governanceContracts[0]).changeAuthorized(Role.AdvisoryBoard, governanceContracts[0].address),
).to.be.reverted;
await expect(
memberRoles.connect(advisoryBoardMember).changeAuthorized(Role.AdvisoryBoard, governanceContracts[0].address),
).to.not.be.reverted;
});

it('should revert if the caller is not authorized', async function () {
const { memberRoles } = this.contracts;
const { defaultSender } = this.accounts;

await expect(
memberRoles.connect(defaultSender).changeAuthorized(Role.AdvisoryBoard, defaultSender.address),
).to.be.revertedWith('Not Authorized');
});
});
43 changes: 43 additions & 0 deletions test/unit/MemberRoles/changeDependentContractAddress.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
const { ethers } = require('hardhat');
const { expect } = require('chai');

const { InternalContractsIDs } = require('../utils').constants;
const { hex } = require('../utils').helpers;

const { AddressZero } = ethers.constants;

describe('changeDependentContractAddress', function () {
it('should change authorized address for the role', async function () {
const { quotationData, memberRoles, master } = this.contracts;
const { governanceContracts, defaultSender } = this.accounts;

await quotationData.connect(governanceContracts[0]).setKycAuthAddress(defaultSender.address);
await memberRoles.connect(governanceContracts[0]).setKycAuthAddress(quotationData.address);

const tkAddressBefore = await memberRoles.internalContracts(InternalContractsIDs.TK);
const tcAddressBefore = await memberRoles.internalContracts(InternalContractsIDs.TC);
const p1AddressBefore = await memberRoles.internalContracts(InternalContractsIDs.P1);
const coAddressBefore = await memberRoles.internalContracts(InternalContractsIDs.CO);

await master.setLatestAddress(hex('CO'), AddressZero);
await master.setTokenAddress(AddressZero);
await master.setLatestAddress(hex('TC'), AddressZero);
await master.setLatestAddress(hex('P1'), AddressZero);

await memberRoles.changeDependentContractAddress();
const tkAddressAfter = await memberRoles.internalContracts(InternalContractsIDs.TK);
const tcAddressAfter = await memberRoles.internalContracts(InternalContractsIDs.TC);
const p1AddressAfter = await memberRoles.internalContracts(InternalContractsIDs.P1);
const coAddressAfter = await memberRoles.internalContracts(InternalContractsIDs.CO);

expect(tkAddressAfter).not.to.be.equal(tkAddressBefore);
expect(p1AddressAfter).not.to.be.equal(tcAddressBefore);
expect(tcAddressAfter).not.to.be.equal(p1AddressBefore);
expect(coAddressAfter).not.to.be.equal(coAddressBefore);

expect(tkAddressAfter).to.be.equal(AddressZero);
expect(tcAddressAfter).to.be.equal(AddressZero);
expect(p1AddressAfter).to.be.equal(AddressZero);
expect(coAddressAfter).to.be.equal(AddressZero);
});
});
25 changes: 25 additions & 0 deletions test/unit/MemberRoles/changeMaxABCount.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const { expect } = require('chai');

describe('changeMaxABCount', function () {
const newMaxABCount = 2;
it('should change max AB count', async function () {
const { memberRoles } = this.contracts;
const { governanceContracts } = this.accounts;

const maxABCountBefore = await memberRoles.maxABCount();
await memberRoles.connect(governanceContracts[0]).changeMaxABCount(newMaxABCount);
const maxABCountAfter = await memberRoles.maxABCount();

expect(maxABCountBefore).not.to.be.eq(maxABCountAfter);
expect(maxABCountAfter).to.be.eq(newMaxABCount);
});

it('should revert if the caller is not authorized to govern', async function () {
const { memberRoles } = this.contracts;
const { defaultSender } = this.accounts;

await expect(memberRoles.connect(defaultSender).changeMaxABCount(newMaxABCount)).to.be.revertedWith(
'Caller is not authorized to govern',
);
});
});
7 changes: 7 additions & 0 deletions test/unit/MemberRoles/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,14 @@ describe('MemberRoles unit tests', function () {
});

require('./join');
require('./changeDependentContractAddress');
require('./updateRole');
require('./switchMembership');
require('./switchMembershipOf');
require('./withdrawMembership');
require('./switchMembershipAndAssets');
require('./swapABMember');
require('./changeAuthorized');
require('./stateManagement');
require('./changeMaxABCount');
});
34 changes: 23 additions & 11 deletions test/unit/MemberRoles/join.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const { expect } = require('chai');
const { ethers, network } = require('hardhat');
const { expectRevert } = require('@openzeppelin/test-helpers');
const { parseUnits } = require('ethers/lib/utils');
const { arrayify, splitSignature } = ethers.utils;
const { expect } = require('chai');

const { signMembershipApproval } = require('../utils').membership;

const { arrayify, parseUnits, splitSignature } = ethers.utils;
const JOINING_FEE = parseUnits('0.002');

describe('join', function () {
Expand Down Expand Up @@ -148,7 +148,22 @@ describe('join', function () {
});

it('reverts when the system is paused', async function () {
// [todo]
const { memberRoles, master } = this.contracts;

await master.pause();
const { nonMembers, defaultSender: kycAuthSigner } = this.accounts;

const membershipApprovalData0 = await signMembershipApproval({
nonce: 0,
address: nonMembers[0].address,
kycAuthSigner,
});

await expect(
memberRoles.join(nonMembers[0].address, 0, arrayify(membershipApprovalData0), {
value: JOINING_FEE,
}),
).to.be.revertedWith('MemberRoles: Emergency pause applied');
});

it('reverts when the value sent is different than the joining fee', async function () {
Expand Down Expand Up @@ -209,12 +224,9 @@ describe('join', function () {

const { compact } = await splitSignature(membershipApprovalData0);

await expectRevert(
memberRoles.join(nonMembers[0].address, 0, arrayify(compact), {
value: JOINING_FEE,
}),
'ECDSA: invalid signature length',
);
await expect(
memberRoles.join(nonMembers[0].address, 0, arrayify(compact), { value: JOINING_FEE }),
).to.be.revertedWith('ECDSA: invalid signature length');
});

it('reverts if the transfer of the joining fee to the pool fails', async function () {
Expand Down
Loading