Skip to content

Commit

Permalink
Add Whitelist contract (OpenZeppelin#746)
Browse files Browse the repository at this point in the history
* Add Whitelist contract
  • Loading branch information
medvedev1088 authored and shrugs committed Mar 8, 2018
1 parent 5a0c104 commit e090a8f
Show file tree
Hide file tree
Showing 3 changed files with 198 additions and 0 deletions.
14 changes: 14 additions & 0 deletions contracts/mocks/WhitelistMock.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
pragma solidity ^0.4.18;

import "../ownership/Whitelist.sol";


contract WhitelistMock is Whitelist {

function onlyWhitelistedCanDoThis()
onlyWhitelisted
view
external
{
}
}
81 changes: 81 additions & 0 deletions contracts/ownership/Whitelist.sol
Original file line number Diff line number Diff line change
@@ -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;
}
}
}

}
103 changes: 103 additions & 0 deletions test/ownership/Whitelist.test.js
Original file line number Diff line number Diff line change
@@ -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 })
);
});
});
});

0 comments on commit e090a8f

Please sign in to comment.