parent
8d4eee412d
commit
d1146e8c8b
@ -0,0 +1,14 @@ |
||||
pragma solidity ^0.4.18; |
||||
|
||||
import "../ownership/Whitelist.sol"; |
||||
|
||||
|
||||
contract WhitelistMock is Whitelist { |
||||
|
||||
function onlyWhitelistedCanDoThis() |
||||
onlyWhitelisted |
||||
view |
||||
external |
||||
{ |
||||
} |
||||
} |
@ -0,0 +1,81 @@ |
||||
pragma solidity ^0.4.18; |
||||
|
||||
|
||||
import "./Ownable.sol"; |
||||
|
||||
|
||||
/** |
||||
* @title Whitelist |
||||
* @dev The Whitelist contract has a whitelist of addresses, and provides basic authorization control functions. |
||||
* @dev This simplifies the implementation of "user permissions". |
||||
*/ |
||||
contract Whitelist is Ownable { |
||||
mapping(address => bool) public whitelist; |
||||
|
||||
event WhitelistedAddressAdded(address addr); |
||||
event WhitelistedAddressRemoved(address addr); |
||||
|
||||
/** |
||||
* @dev Throws if called by any account that's not whitelisted. |
||||
*/ |
||||
modifier onlyWhitelisted() { |
||||
require(whitelist[msg.sender]); |
||||
_; |
||||
} |
||||
|
||||
/** |
||||
* @dev add an address to the whitelist |
||||
* @param addr address |
||||
* @return true if the address was added to the whitelist, false if the address was already in the whitelist |
||||
*/ |
||||
function addAddressToWhitelist(address addr) onlyOwner public returns(bool success) { |
||||
if (!whitelist[addr]) { |
||||
whitelist[addr] = true; |
||||
WhitelistedAddressAdded(addr); |
||||
success = true; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @dev add addresses to the whitelist |
||||
* @param addrs addresses |
||||
* @return true if at least one address was added to the whitelist, |
||||
* false if all addresses were already in the whitelist |
||||
*/ |
||||
function addAddressesToWhitelist(address[] addrs) onlyOwner public returns(bool success) { |
||||
for (uint256 i = 0; i < addrs.length; i++) { |
||||
if (addAddressToWhitelist(addrs[i])) { |
||||
success = true; |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @dev remove an address from the whitelist |
||||
* @param addr address |
||||
* @return true if the address was removed from the whitelist, |
||||
* false if the address wasn't in the whitelist in the first place |
||||
*/ |
||||
function removeAddressFromWhitelist(address addr) onlyOwner public returns(bool success) { |
||||
if (whitelist[addr]) { |
||||
whitelist[addr] = false; |
||||
WhitelistedAddressRemoved(addr); |
||||
success = true; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @dev remove addresses from the whitelist |
||||
* @param addrs addresses |
||||
* @return true if at least one address was removed from the whitelist, |
||||
* false if all addresses weren't in the whitelist in the first place |
||||
*/ |
||||
function removeAddressesFromWhitelist(address[] addrs) onlyOwner public returns(bool success) { |
||||
for (uint256 i = 0; i < addrs.length; i++) { |
||||
if (removeAddressFromWhitelist(addrs[i])) { |
||||
success = true; |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,103 @@ |
||||
import expectThrow from '../helpers/expectThrow'; |
||||
import expectEvent from '../helpers/expectEvent'; |
||||
|
||||
const WhitelistMock = artifacts.require('WhitelistMock'); |
||||
|
||||
require('chai') |
||||
.use(require('chai-as-promised')) |
||||
.should(); |
||||
|
||||
contract('Whitelist', function (accounts) { |
||||
let mock; |
||||
|
||||
const [ |
||||
owner, |
||||
whitelistedAddress1, |
||||
whitelistedAddress2, |
||||
anyone, |
||||
] = accounts; |
||||
|
||||
const whitelistedAddresses = [whitelistedAddress1, whitelistedAddress2]; |
||||
|
||||
before(async function () { |
||||
mock = await WhitelistMock.new(); |
||||
}); |
||||
|
||||
context('in normal conditions', () => { |
||||
it('should add address to the whitelist', async function () { |
||||
await expectEvent.inTransaction( |
||||
mock.addAddressToWhitelist(whitelistedAddress1, { from: owner }), |
||||
'WhitelistedAddressAdded' |
||||
); |
||||
const isWhitelisted = await mock.whitelist(whitelistedAddress1); |
||||
isWhitelisted.should.be.equal(true); |
||||
}); |
||||
|
||||
it('should add addresses to the whitelist', async function () { |
||||
await expectEvent.inTransaction( |
||||
mock.addAddressesToWhitelist(whitelistedAddresses, { from: owner }), |
||||
'WhitelistedAddressAdded' |
||||
); |
||||
for (let addr of whitelistedAddresses) { |
||||
const isWhitelisted = await mock.whitelist(addr); |
||||
isWhitelisted.should.be.equal(true); |
||||
} |
||||
}); |
||||
|
||||
it('should not announce WhitelistedAddressAdded event if address is already in the whitelist', async function () { |
||||
const { logs } = await mock.addAddressToWhitelist(whitelistedAddress1, { from: owner }); |
||||
logs.should.be.empty; |
||||
}); |
||||
|
||||
it('should remove address from the whitelist', async function () { |
||||
await expectEvent.inTransaction( |
||||
mock.removeAddressFromWhitelist(whitelistedAddress1, { from: owner }), |
||||
'WhitelistedAddressRemoved' |
||||
); |
||||
let isWhitelisted = await mock.whitelist(whitelistedAddress1); |
||||
isWhitelisted.should.be.equal(false); |
||||
}); |
||||
|
||||
it('should remove addresses from the the whitelist', async function () { |
||||
await expectEvent.inTransaction( |
||||
mock.removeAddressesFromWhitelist(whitelistedAddresses, { from: owner }), |
||||
'WhitelistedAddressRemoved' |
||||
); |
||||
for (let addr of whitelistedAddresses) { |
||||
const isWhitelisted = await mock.whitelist(addr); |
||||
isWhitelisted.should.be.equal(false); |
||||
} |
||||
}); |
||||
|
||||
it('should not announce WhitelistedAddressRemoved event if address is not in the whitelist', async function () { |
||||
const { logs } = await mock.removeAddressFromWhitelist(whitelistedAddress1, { from: owner }); |
||||
logs.should.be.empty; |
||||
}); |
||||
|
||||
it('should allow whitelisted address to call #onlyWhitelistedCanDoThis', async () => { |
||||
await mock.addAddressToWhitelist(whitelistedAddress1, { from: owner }); |
||||
await mock.onlyWhitelistedCanDoThis({ from: whitelistedAddress1 }) |
||||
.should.be.fulfilled; |
||||
}); |
||||
}); |
||||
|
||||
context('in adversarial conditions', () => { |
||||
it('should not allow "anyone" to add to the whitelist', async () => { |
||||
await expectThrow( |
||||
mock.addAddressToWhitelist(whitelistedAddress1, { from: anyone }) |
||||
); |
||||
}); |
||||
|
||||
it('should not allow "anyone" to remove from the whitelist', async () => { |
||||
await expectThrow( |
||||
mock.removeAddressFromWhitelist(whitelistedAddress1, { from: anyone }) |
||||
); |
||||
}); |
||||
|
||||
it('should not allow "anyone" to call #onlyWhitelistedCanDoThis', async () => { |
||||
await expectThrow( |
||||
mock.onlyWhitelistedCanDoThis({ from: anyone }) |
||||
); |
||||
}); |
||||
}); |
||||
}); |
Loading…
Reference in new issue