-
Notifications
You must be signed in to change notification settings - Fork 11.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Whitelist contract #746
Merged
Merged
Changes from 10 commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
49b9c9f
Add Whitelist contract
medvedev-evgeny fc57d6a
Rename events in Whitelist.so
40c91b1
Merge branch 'master' into feature/whitelist
medvedev1088 2f95e63
Remove owner check in onlyWhitelist modifier
3985369
Add functions that allow adding and removing arrays of addresses to t…
96a30aa
Change the compiler version in WhitelistMock.sol
f90a774
Fix linter error
16b5fd7
Fix the documentation for onlyWhitelisted
5ecc3e3
Fix concurrency in tests
9a002ba
Merge branch 'master' into feature/whitelist
medvedev1088 025c9bd
Add @dev for multiline dev comments
medvedev1088 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
{ | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, 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; | ||
} | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 }) | ||
); | ||
}); | ||
}); | ||
}); |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's add an
@dev
prefix here for multiple-line dev commentsThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.