RBAC and Ownable migration towards Roles (#1291)
* Role tests (#1228)
* Moved RBAC tests to access.
* Added Roles.addMany and tests.
* Fixed linter error.
* Now using uint256 indexes.
* Removed RBAC tokens (#1229)
* Deleted RBACCappedTokenMock.
* Removed RBACMintableToken.
* Removed RBACMintableToken from the MintedCrowdsale tests.
* Roles can now be transfered. (#1235)
* Roles can now be transfered.
* Now explicitly checking support for the null address.
* Now rejecting transfer to a role-haver.
* Added renounce, roles can no longer be transfered to 0.
* Fixed linter errors.
* Fixed a Roles test.
* True Ownership (#1247)
* Added barebones Secondary.
* Added transferPrimary
* Escrow is now Secondary instead of Ownable.
* Now reverting on transfers to 0.
* The Secondary's primary is now private.
* MintableToken using Roles (#1236)
* Minor test style improvements (#1219)
* Changed .eq to .equal
* Changed equal(bool) to .to.be.bool
* Changed be.bool to equal(bool), disallowed unused expressions.
* Add ERC165Query library (#1086)
* Add ERC165Query library
* Address PR Comments
* Add tests and mocks from #1024 and refactor code slightly
* Fix javascript and solidity linting errors
* Split supportsInterface into three methods as discussed in #1086
* Change InterfaceId_ERC165 comment to match style in the rest of the repo
* Fix max-len lint issue on ERC165Checker.sol
* Conditionally ignore the asserts during solidity-coverage test
* Switch to abi.encodeWithSelector and add test for account addresses
* Switch to supportsInterfaces API as suggested by @frangio
* Adding ERC165InterfacesSupported.sol
* Fix style issues
* Add test for supportsInterfaces returning false
* Add ERC165Checker.sol newline
* feat: fix coverage implementation
* fix: solidity linting error
* fix: revert to using boolean tests instead of require statements
* fix: make supportsERC165Interface private again
* rename SupportsInterfaceWithLookupMock to avoid name clashing
* Added mint and burn tests for zero amounts. (#1230)
* Changed .eq to .equal. (#1231)
* ERC721 pausable token (#1154)
* ERC721 pausable token
* Reuse of ERC721 Basic behavior for Pausable, split view checks in paused state & style fixes
* [~] paused token behavior
* Add some detail to releasing steps (#1190)
* add note about pulling upstream changes to release branch
* add comment about upstream changes in merging section
* Increase test coverage (#1237)
* Fixed a SplitPayment test
* Deleted unnecessary function.
* Improved PostDeliveryCrowdsale tests.
* Improved RefundableCrowdsale tests.
* Improved MintedCrowdsale tests.
* Improved IncreasingPriceCrowdsale tests.
* Fixed a CappedCrowdsale test.
* Improved TimedCrowdsale tests.
* Improved descriptions of added tests.
* ci: trigger docs update on tag (#1186)
* MintableToken now uses Roles.
* Fixed FinalizableCrowdsale test.
* Roles can now be transfered.
* Fixed tests related to MintableToken.
* Removed Roles.check.
* Renamed transferMintPermission.
* Moved MinterRole
* Fixed RBAC.
* Adressed review comments.
* Addressed review comments
* Fixed linter errors.
* Added Events tests of Pausable contract (#1207)
* Fixed roles tests.
* Rename events to past-tense (#1181)
* fix: refactor sign.js and related tests (#1243)
* fix: refactor sign.js and related tests
* fix: remove unused dep
* fix: update package.json correctly
* Added "_" sufix to internal variables (#1171)
* Added PublicRole test.
* Fixed crowdsale tests.
* Rename ERC interfaces to I prefix (#1252)
* rename ERC20 to IERC20
* move ERC20.sol to IERC20.sol
* rename StandardToken to ERC20
* rename StandardTokenMock to ERC20Mock
* move StandardToken.sol to ERC20.sol, likewise test and mock files
* rename MintableToken to ERC20Mintable
* move MintableToken.sol to ERC20Mintable.sol, likewise test and mock files
* rename BurnableToken to ERC20Burnable
* move BurnableToken.sol to ERC20Burnable.sol, likewise for related files
* rename CappedToken to ERC20Capped
* move CappedToken.sol to ERC20Capped.sol, likewise for related files
* rename PausableToken to ERC20Pausable
* move PausableToken.sol to ERC20Pausable.sol, likewise for related files
* rename DetailedERC20 to ERC20Detailed
* move DetailedERC20.sol to ERC20Detailed.sol, likewise for related files
* rename ERC721 to IERC721, and likewise for other related interfaces
* move ERC721.sol to IERC721.sol, likewise for other 721 interfaces
* rename ERC721Token to ERC721
* move ERC721Token.sol to ERC721.sol, likewise for related files
* rename ERC721BasicToken to ERC721Basic
* move ERC721BasicToken.sol to ERC721Basic.sol, likewise for related files
* rename ERC721PausableToken to ERC721Pausable
* move ERC721PausableToken.sol to ERC721Pausable.sol
* rename ERC165 to IERC165
* move ERC165.sol to IERC165.sol
* amend comment that ERC20 is based on FirstBlood
* fix comments mentioning IERC721Receiver
* added explicit visibility (#1261)
* Remove underscores from event parameters. (#1258)
* Remove underscores from event parameters.
Fixes #1175
* Add comment about ERC
* Move contracts to subdirectories (#1253)
* Move contracts to subdirectories
Fixes #1177.
This Change also removes the LimitBalance contract.
* fix import
* move MerkleProof to cryptography
* Fix import
* Remove HasNoEther, HasNoTokens, HasNoContracts, and NoOwner (#1254)
* remove HasNoEther, HasNoTokens, HasNoContracts, and NoOwner
* remove unused ERC223TokenMock
* remove Contactable
* remove TokenDestructible
* remove DeprecatedERC721
* inline Destructible#destroy in Bounty
* remove Destructible
* Functions in interfaces changed to "external" (#1263)
* Add a leading underscore to internal and private functions. (#1257)
* Add a leading underscore to internal and private functions.
Fixes #1176
* Remove super
* update the ERC721 changes
* add missing underscore after merge
* Fix mock
* Improve encapsulation on SignatureBouncer, Whitelist and RBAC example (#1265)
* Improve encapsulation on Whitelist
* remove only
* update whitelisted crowdsale test
* Improve encapsulation on SignatureBouncer
* fix missing test
* Improve encapsulation on RBAC example
* Improve encapsulation on RBAC example
* Remove extra visibility
* Improve encapsulation on ERC20 Mintable
* Improve encapsulation on Superuser
* fix lint
* add missing constant
* Addressed review comments.
* Fixed build error.
* Improved Roles API. (#1280)
* Improved Roles API.
* fix linter error
* Added PauserRole. (#1283)
* Remove Claimable, DelayedClaimable, Heritable (#1274)
* remove Claimable, DelayedClaimable, Heritable
* remove SimpleSavingsWallet example which used Heritable
(cherry picked from commit 0dc711732a)
* Role behavior tests (#1285)
* Added role tests.
* Added PauserRole tests to contracts that have that role.
* Added MinterRole tests to contracts that have that role.
* Fixed linter errors.
* Migrate Ownable to Roles (#1287)
* Added CapperRole.
* RefundEscrow is now Secondary.
* FinalizableCrowdsale is no longer Ownable.
* Removed Whitelist and WhitelistedCrowdsale, redesign needed.
* Fixed linter errors, disabled lbrace due to it being buggy.
* Remove RBAC, SignatureBouncer refactor (#1289)
* Added CapperRole.
* RefundEscrow is now Secondary.
* FinalizableCrowdsale is no longer Ownable.
* Removed Whitelist and WhitelistedCrowdsale, redesign needed.
* Fixed linter errors, disabled lbrace due to it being buggy.
* Moved SignatureBouncer tests.
* Deleted RBAC and Superuser.
* Deleted rbac directory.
* Updated readme.
* SignatureBouncer now uses SignerRole, renamed bouncer to signer.
* feat: implement ERC721Mintable and ERC721Burnable (#1276)
* feat: implement ERC721Mintable and ERC721Burnable
* fix: linting errors
* fix: remove unused mintable mock for ERC721BasicMock
* fix: add finishMinting tests
* fix: catch MintFinished typo
* inline ERC721Full behavior
* undo pretty formatting
* fix lint errors
* rename canMint to onlyBeforeMintingFinished for consistency with ERC20Mintable
* Fix the merge with the privatization branch
* remove duplicate CapperRole test
This commit is contained in:
61
test/access/Roles.test.js
Normal file
61
test/access/Roles.test.js
Normal file
@ -0,0 +1,61 @@
|
||||
const RolesMock = artifacts.require('RolesMock');
|
||||
|
||||
require('chai')
|
||||
.should();
|
||||
|
||||
contract('Roles', function ([_, authorized, otherAuthorized, anyone]) {
|
||||
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
|
||||
|
||||
beforeEach(async function () {
|
||||
this.roles = await RolesMock.new();
|
||||
});
|
||||
|
||||
context('initially', function () {
|
||||
it('doesn\'t pre-assign roles', async function () {
|
||||
(await this.roles.has(authorized)).should.equal(false);
|
||||
(await this.roles.has(otherAuthorized)).should.equal(false);
|
||||
(await this.roles.has(anyone)).should.equal(false);
|
||||
});
|
||||
|
||||
describe('adding roles', function () {
|
||||
it('adds roles to a single account', async function () {
|
||||
await this.roles.add(authorized);
|
||||
(await this.roles.has(authorized)).should.equal(true);
|
||||
(await this.roles.has(anyone)).should.equal(false);
|
||||
});
|
||||
|
||||
it('adds roles to an already-assigned account', async function () {
|
||||
await this.roles.add(authorized);
|
||||
await this.roles.add(authorized);
|
||||
(await this.roles.has(authorized)).should.equal(true);
|
||||
});
|
||||
|
||||
it('doesn\'t revert when adding roles to the null account', async function () {
|
||||
await this.roles.add(ZERO_ADDRESS);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('with added roles', function () {
|
||||
beforeEach(async function () {
|
||||
await this.roles.add(authorized);
|
||||
await this.roles.add(otherAuthorized);
|
||||
});
|
||||
|
||||
describe('removing roles', function () {
|
||||
it('removes a single role', async function () {
|
||||
await this.roles.remove(authorized);
|
||||
(await this.roles.has(authorized)).should.equal(false);
|
||||
(await this.roles.has(otherAuthorized)).should.equal(true);
|
||||
});
|
||||
|
||||
it('doesn\'t revert when removing unassigned roles', async function () {
|
||||
await this.roles.remove(anyone);
|
||||
});
|
||||
|
||||
it('doesn\'t revert when removing roles from the null account', async function () {
|
||||
await this.roles.remove(ZERO_ADDRESS);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1,246 +0,0 @@
|
||||
const { assertRevert } = require('../helpers/assertRevert');
|
||||
const { getBouncerSigner } = require('../helpers/sign');
|
||||
|
||||
const Bouncer = artifacts.require('SignatureBouncerMock');
|
||||
|
||||
const BigNumber = web3.BigNumber;
|
||||
|
||||
require('chai')
|
||||
.use(require('chai-bignumber')(BigNumber))
|
||||
.should();
|
||||
|
||||
const UINT_VALUE = 23;
|
||||
const BYTES_VALUE = web3.toHex('test');
|
||||
const INVALID_SIGNATURE = '0xabcd';
|
||||
|
||||
contract('Bouncer', function ([_, owner, anyone, bouncerAddress, authorizedUser]) {
|
||||
beforeEach(async function () {
|
||||
this.bouncer = await Bouncer.new({ from: owner });
|
||||
});
|
||||
|
||||
context('management', function () {
|
||||
it('has a default owner of self', async function () {
|
||||
(await this.bouncer.owner()).should.equal(owner);
|
||||
});
|
||||
|
||||
it('allows the owner to add a bouncer', async function () {
|
||||
await this.bouncer.addBouncer(bouncerAddress, { from: owner });
|
||||
(await this.bouncer.isBouncer(bouncerAddress)).should.equal(true);
|
||||
});
|
||||
|
||||
it('does not allow adding an invalid address', async function () {
|
||||
await assertRevert(
|
||||
this.bouncer.addBouncer('0x0', { from: owner })
|
||||
);
|
||||
});
|
||||
|
||||
it('allows the owner to remove a bouncer', async function () {
|
||||
await this.bouncer.addBouncer(bouncerAddress, { from: owner });
|
||||
|
||||
await this.bouncer.removeBouncer(bouncerAddress, { from: owner });
|
||||
(await this.bouncer.isBouncer(bouncerAddress)).should.equal(false);
|
||||
});
|
||||
|
||||
it('does not allow anyone to add a bouncer', async function () {
|
||||
await assertRevert(
|
||||
this.bouncer.addBouncer(bouncerAddress, { from: anyone })
|
||||
);
|
||||
});
|
||||
|
||||
it('does not allow anyone to remove a bouncer', async function () {
|
||||
await this.bouncer.addBouncer(bouncerAddress, { from: owner });
|
||||
|
||||
await assertRevert(
|
||||
this.bouncer.removeBouncer(bouncerAddress, { from: anyone })
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('with bouncer address', function () {
|
||||
beforeEach(async function () {
|
||||
await this.bouncer.addBouncer(bouncerAddress, { from: owner });
|
||||
this.signFor = getBouncerSigner(this.bouncer, bouncerAddress);
|
||||
});
|
||||
|
||||
describe('modifiers', function () {
|
||||
context('plain signature', function () {
|
||||
it('allows valid signature for sender', async function () {
|
||||
await this.bouncer.onlyWithValidSignature(this.signFor(authorizedUser), { from: authorizedUser });
|
||||
});
|
||||
|
||||
it('does not allow invalid signature for sender', async function () {
|
||||
await assertRevert(
|
||||
this.bouncer.onlyWithValidSignature(INVALID_SIGNATURE, { from: authorizedUser })
|
||||
);
|
||||
});
|
||||
|
||||
it('does not allow valid signature for other sender', async function () {
|
||||
await assertRevert(
|
||||
this.bouncer.onlyWithValidSignature(this.signFor(authorizedUser), { from: anyone })
|
||||
);
|
||||
});
|
||||
|
||||
it('does not allow valid signature for method for sender', async function () {
|
||||
await assertRevert(
|
||||
this.bouncer.onlyWithValidSignature(this.signFor(authorizedUser, 'onlyWithValidSignature'),
|
||||
{ from: authorizedUser })
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('method signature', function () {
|
||||
it('allows valid signature with correct method for sender', async function () {
|
||||
await this.bouncer.onlyWithValidSignatureAndMethod(
|
||||
this.signFor(authorizedUser, 'onlyWithValidSignatureAndMethod'), { from: authorizedUser }
|
||||
);
|
||||
});
|
||||
|
||||
it('does not allow invalid signature with correct method for sender', async function () {
|
||||
await assertRevert(
|
||||
this.bouncer.onlyWithValidSignatureAndMethod(INVALID_SIGNATURE, { from: authorizedUser })
|
||||
);
|
||||
});
|
||||
|
||||
it('does not allow valid signature with correct method for other sender', async function () {
|
||||
await assertRevert(
|
||||
this.bouncer.onlyWithValidSignatureAndMethod(
|
||||
this.signFor(authorizedUser, 'onlyWithValidSignatureAndMethod'), { from: anyone }
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('does not allow valid method signature with incorrect method for sender', async function () {
|
||||
await assertRevert(
|
||||
this.bouncer.onlyWithValidSignatureAndMethod(this.signFor(authorizedUser, 'theWrongMethod'),
|
||||
{ from: authorizedUser })
|
||||
);
|
||||
});
|
||||
|
||||
it('does not allow valid non-method signature method for sender', async function () {
|
||||
await assertRevert(
|
||||
this.bouncer.onlyWithValidSignatureAndMethod(this.signFor(authorizedUser), { from: authorizedUser })
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('method and data signature', function () {
|
||||
it('allows valid signature with correct method and data for sender', async function () {
|
||||
await this.bouncer.onlyWithValidSignatureAndData(UINT_VALUE,
|
||||
this.signFor(authorizedUser, 'onlyWithValidSignatureAndData', [UINT_VALUE]), { from: authorizedUser }
|
||||
);
|
||||
});
|
||||
|
||||
it('does not allow invalid signature with correct method and data for sender', async function () {
|
||||
await assertRevert(
|
||||
this.bouncer.onlyWithValidSignatureAndData(UINT_VALUE, INVALID_SIGNATURE, { from: authorizedUser })
|
||||
);
|
||||
});
|
||||
|
||||
it('does not allow valid signature with correct method and incorrect data for sender', async function () {
|
||||
await assertRevert(
|
||||
this.bouncer.onlyWithValidSignatureAndData(UINT_VALUE + 10,
|
||||
this.signFor(authorizedUser, 'onlyWithValidSignatureAndData', [UINT_VALUE]),
|
||||
{ from: authorizedUser }
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('does not allow valid signature with correct method and data for other sender', async function () {
|
||||
await assertRevert(
|
||||
this.bouncer.onlyWithValidSignatureAndData(UINT_VALUE,
|
||||
this.signFor(authorizedUser, 'onlyWithValidSignatureAndData', [UINT_VALUE]),
|
||||
{ from: anyone }
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('does not allow valid non-method signature for sender', async function () {
|
||||
await assertRevert(
|
||||
this.bouncer.onlyWithValidSignatureAndData(UINT_VALUE,
|
||||
this.signFor(authorizedUser), { from: authorizedUser }
|
||||
)
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('signature validation', function () {
|
||||
context('plain signature', function () {
|
||||
it('validates valid signature for valid user', async function () {
|
||||
(await this.bouncer.checkValidSignature(authorizedUser, this.signFor(authorizedUser))).should.equal(true);
|
||||
});
|
||||
|
||||
it('does not validate invalid signature for valid user', async function () {
|
||||
(await this.bouncer.checkValidSignature(authorizedUser, INVALID_SIGNATURE)).should.equal(false);
|
||||
});
|
||||
|
||||
it('does not validate valid signature for anyone', async function () {
|
||||
(await this.bouncer.checkValidSignature(anyone, this.signFor(authorizedUser))).should.equal(false);
|
||||
});
|
||||
|
||||
it('does not validate valid signature for method for valid user', async function () {
|
||||
(await this.bouncer.checkValidSignature(authorizedUser, this.signFor(authorizedUser, 'checkValidSignature'))
|
||||
).should.equal(false);
|
||||
});
|
||||
});
|
||||
|
||||
context('method signature', function () {
|
||||
it('validates valid signature with correct method for valid user', async function () {
|
||||
(await this.bouncer.checkValidSignatureAndMethod(authorizedUser,
|
||||
this.signFor(authorizedUser, 'checkValidSignatureAndMethod'))
|
||||
).should.equal(true);
|
||||
});
|
||||
|
||||
it('does not validate invalid signature with correct method for valid user', async function () {
|
||||
(await this.bouncer.checkValidSignatureAndMethod(authorizedUser, INVALID_SIGNATURE)).should.equal(false);
|
||||
});
|
||||
|
||||
it('does not validate valid signature with correct method for anyone', async function () {
|
||||
(await this.bouncer.checkValidSignatureAndMethod(anyone,
|
||||
this.signFor(authorizedUser, 'checkValidSignatureAndMethod'))
|
||||
).should.equal(false);
|
||||
});
|
||||
|
||||
it('does not validate valid non-method signature with correct method for valid user', async function () {
|
||||
(await this.bouncer.checkValidSignatureAndMethod(authorizedUser, this.signFor(authorizedUser))
|
||||
).should.equal(false);
|
||||
});
|
||||
});
|
||||
|
||||
context('method and data signature', function () {
|
||||
it('validates valid signature with correct method and data for valid user', async function () {
|
||||
(await this.bouncer.checkValidSignatureAndData(authorizedUser, BYTES_VALUE, UINT_VALUE,
|
||||
this.signFor(authorizedUser, 'checkValidSignatureAndData', [authorizedUser, BYTES_VALUE, UINT_VALUE]))
|
||||
).should.equal(true);
|
||||
});
|
||||
|
||||
it('does not validate invalid signature with correct method and data for valid user', async function () {
|
||||
(await this.bouncer.checkValidSignatureAndData(authorizedUser, BYTES_VALUE, UINT_VALUE, INVALID_SIGNATURE)
|
||||
).should.equal(false);
|
||||
});
|
||||
|
||||
it('does not validate valid signature with correct method and incorrect data for valid user',
|
||||
async function () {
|
||||
(await this.bouncer.checkValidSignatureAndData(authorizedUser, BYTES_VALUE, UINT_VALUE + 10,
|
||||
this.signFor(authorizedUser, 'checkValidSignatureAndData', [authorizedUser, BYTES_VALUE, UINT_VALUE]))
|
||||
).should.equal(false);
|
||||
}
|
||||
);
|
||||
|
||||
it('does not validate valid signature with correct method and data for anyone', async function () {
|
||||
(await this.bouncer.checkValidSignatureAndData(anyone, BYTES_VALUE, UINT_VALUE,
|
||||
this.signFor(authorizedUser, 'checkValidSignatureAndData', [authorizedUser, BYTES_VALUE, UINT_VALUE]))
|
||||
).should.equal(false);
|
||||
});
|
||||
|
||||
it('does not validate valid non-method-data signature with correct method and data for valid user',
|
||||
async function () {
|
||||
(await this.bouncer.checkValidSignatureAndData(authorizedUser, BYTES_VALUE, UINT_VALUE,
|
||||
this.signFor(authorizedUser, 'checkValidSignatureAndData'))
|
||||
).should.equal(false);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1,65 +0,0 @@
|
||||
const { expectThrow } = require('../helpers/expectThrow');
|
||||
|
||||
const WhitelistMock = artifacts.require('WhitelistMock');
|
||||
|
||||
require('chai')
|
||||
.should();
|
||||
|
||||
contract('Whitelist', function ([_, owner, whitelistedAddress1, whitelistedAddress2, anyone]) {
|
||||
const whitelistedAddresses = [whitelistedAddress1, whitelistedAddress2];
|
||||
|
||||
beforeEach(async function () {
|
||||
this.mock = await WhitelistMock.new({ from: owner });
|
||||
});
|
||||
|
||||
context('in normal conditions', function () {
|
||||
it('should add address to the whitelist', async function () {
|
||||
await this.mock.addAddressToWhitelist(whitelistedAddress1, { from: owner });
|
||||
(await this.mock.isWhitelisted(whitelistedAddress1)).should.equal(true);
|
||||
});
|
||||
|
||||
it('should add addresses to the whitelist', async function () {
|
||||
await this.mock.addAddressesToWhitelist(whitelistedAddresses, { from: owner });
|
||||
for (const addr of whitelistedAddresses) {
|
||||
(await this.mock.isWhitelisted(addr)).should.equal(true);
|
||||
}
|
||||
});
|
||||
|
||||
it('should remove address from the whitelist', async function () {
|
||||
await this.mock.removeAddressFromWhitelist(whitelistedAddress1, { from: owner });
|
||||
(await this.mock.isWhitelisted(whitelistedAddress1)).should.equal(false);
|
||||
});
|
||||
|
||||
it('should remove addresses from the the whitelist', async function () {
|
||||
await this.mock.removeAddressesFromWhitelist(whitelistedAddresses, { from: owner });
|
||||
for (const addr of whitelistedAddresses) {
|
||||
(await this.mock.isWhitelisted(addr)).should.equal(false);
|
||||
}
|
||||
});
|
||||
|
||||
it('should allow whitelisted address to call #onlyWhitelistedCanDoThis', async function () {
|
||||
await this.mock.addAddressToWhitelist(whitelistedAddress1, { from: owner });
|
||||
await this.mock.onlyWhitelistedCanDoThis({ from: whitelistedAddress1 });
|
||||
});
|
||||
});
|
||||
|
||||
context('in adversarial conditions', function () {
|
||||
it('should not allow "anyone" to add to the whitelist', async function () {
|
||||
await expectThrow(
|
||||
this.mock.addAddressToWhitelist(whitelistedAddress1, { from: anyone })
|
||||
);
|
||||
});
|
||||
|
||||
it('should not allow "anyone" to remove from the whitelist', async function () {
|
||||
await expectThrow(
|
||||
this.mock.removeAddressFromWhitelist(whitelistedAddress1, { from: anyone })
|
||||
);
|
||||
});
|
||||
|
||||
it('should not allow "anyone" to call #onlyWhitelistedCanDoThis', async function () {
|
||||
await expectThrow(
|
||||
this.mock.onlyWhitelistedCanDoThis({ from: anyone })
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
11
test/access/roles/CapperRole.test.js
Normal file
11
test/access/roles/CapperRole.test.js
Normal file
@ -0,0 +1,11 @@
|
||||
const { shouldBehaveLikePublicRole } = require('../../access/roles/PublicRole.behavior');
|
||||
const CapperRoleMock = artifacts.require('CapperRoleMock');
|
||||
|
||||
contract('CapperRole', function ([_, capper, otherCapper, ...otherAccounts]) {
|
||||
beforeEach(async function () {
|
||||
this.contract = await CapperRoleMock.new({ from: capper });
|
||||
await this.contract.addCapper(otherCapper, { from: capper });
|
||||
});
|
||||
|
||||
shouldBehaveLikePublicRole(capper, otherCapper, otherAccounts, 'capper');
|
||||
});
|
||||
11
test/access/roles/MinterRole.test.js
Normal file
11
test/access/roles/MinterRole.test.js
Normal file
@ -0,0 +1,11 @@
|
||||
const { shouldBehaveLikePublicRole } = require('../../access/roles/PublicRole.behavior');
|
||||
const MinterRoleMock = artifacts.require('MinterRoleMock');
|
||||
|
||||
contract('MinterRole', function ([_, minter, otherMinter, ...otherAccounts]) {
|
||||
beforeEach(async function () {
|
||||
this.contract = await MinterRoleMock.new({ from: minter });
|
||||
await this.contract.addMinter(otherMinter, { from: minter });
|
||||
});
|
||||
|
||||
shouldBehaveLikePublicRole(minter, otherMinter, otherAccounts, 'minter');
|
||||
});
|
||||
11
test/access/roles/PauserRole.test.js
Normal file
11
test/access/roles/PauserRole.test.js
Normal file
@ -0,0 +1,11 @@
|
||||
const { shouldBehaveLikePublicRole } = require('../../access/roles/PublicRole.behavior');
|
||||
const PauserRoleMock = artifacts.require('PauserRoleMock');
|
||||
|
||||
contract('PauserRole', function ([_, pauser, otherPauser, ...otherAccounts]) {
|
||||
beforeEach(async function () {
|
||||
this.contract = await PauserRoleMock.new({ from: pauser });
|
||||
await this.contract.addPauser(otherPauser, { from: pauser });
|
||||
});
|
||||
|
||||
shouldBehaveLikePublicRole(pauser, otherPauser, otherAccounts, 'pauser');
|
||||
});
|
||||
66
test/access/roles/PublicRole.behavior.js
Normal file
66
test/access/roles/PublicRole.behavior.js
Normal file
@ -0,0 +1,66 @@
|
||||
require('chai')
|
||||
.should();
|
||||
|
||||
function capitalize (str) {
|
||||
return str.replace(/\b\w/g, l => l.toUpperCase());
|
||||
}
|
||||
|
||||
function shouldBehaveLikePublicRole (authorized, otherAuthorized, [anyone], rolename) {
|
||||
rolename = capitalize(rolename);
|
||||
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
|
||||
|
||||
describe('should behave like public role', function () {
|
||||
beforeEach('check preconditions', async function () {
|
||||
(await this.contract[`is${rolename}`](authorized)).should.equal(true);
|
||||
(await this.contract[`is${rolename}`](otherAuthorized)).should.equal(true);
|
||||
(await this.contract[`is${rolename}`](anyone)).should.equal(false);
|
||||
});
|
||||
|
||||
describe('add', function () {
|
||||
it('adds role to a new account', async function () {
|
||||
await this.contract[`add${rolename}`](anyone, { from: authorized });
|
||||
(await this.contract[`is${rolename}`](anyone)).should.equal(true);
|
||||
});
|
||||
|
||||
it('adds role to an already-assigned account', async function () {
|
||||
await this.contract[`add${rolename}`](authorized, { from: authorized });
|
||||
(await this.contract[`is${rolename}`](authorized)).should.equal(true);
|
||||
});
|
||||
|
||||
it('doesn\'t revert when adding role to the null account', async function () {
|
||||
await this.contract[`add${rolename}`](ZERO_ADDRESS, { from: authorized });
|
||||
});
|
||||
});
|
||||
|
||||
describe('remove', function () {
|
||||
it('removes role from an already assigned account', async function () {
|
||||
await this.contract[`remove${rolename}`](authorized);
|
||||
(await this.contract[`is${rolename}`](authorized)).should.equal(false);
|
||||
(await this.contract[`is${rolename}`](otherAuthorized)).should.equal(true);
|
||||
});
|
||||
|
||||
it('doesn\'t revert when removing from an unassigned account', async function () {
|
||||
await this.contract[`remove${rolename}`](anyone);
|
||||
});
|
||||
|
||||
it('doesn\'t revert when removing role from the null account', async function () {
|
||||
await this.contract[`remove${rolename}`](ZERO_ADDRESS);
|
||||
});
|
||||
});
|
||||
|
||||
describe('renouncing roles', function () {
|
||||
it('renounces an assigned role', async function () {
|
||||
await this.contract[`renounce${rolename}`]({ from: authorized });
|
||||
(await this.contract[`is${rolename}`](authorized)).should.equal(false);
|
||||
});
|
||||
|
||||
it('doesn\'t revert when renouncing unassigned role', async function () {
|
||||
await this.contract[`renounce${rolename}`]({ from: anyone });
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
shouldBehaveLikePublicRole,
|
||||
};
|
||||
11
test/access/roles/SignerRole.test.js
Normal file
11
test/access/roles/SignerRole.test.js
Normal file
@ -0,0 +1,11 @@
|
||||
const { shouldBehaveLikePublicRole } = require('../../access/roles/PublicRole.behavior');
|
||||
const SignerRoleMock = artifacts.require('SignerRoleMock');
|
||||
|
||||
contract('SignerRole', function ([_, signer, otherSigner, ...otherAccounts]) {
|
||||
beforeEach(async function () {
|
||||
this.contract = await SignerRoleMock.new({ from: signer });
|
||||
await this.contract.addSigner(otherSigner, { from: signer });
|
||||
});
|
||||
|
||||
shouldBehaveLikePublicRole(signer, otherSigner, otherAccounts, 'signer');
|
||||
});
|
||||
Reference in New Issue
Block a user