wayback/contracts/implementation/AddressWhitelist.sol
2022-10-09 03:35:34 -03:00

88 lines
3.2 KiB
Solidity

// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.8.0;
import "../interfaces/AddressWhitelistInterface.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./Lockable.sol";
/**
* @title A contract to track a whitelist of addresses.
*/
contract AddressWhitelist is AddressWhitelistInterface, Ownable, Lockable {
enum Status { None, In, Out }
mapping(address => Status) public whitelist;
address[] public whitelistIndices;
event AddedToWhitelist(address indexed addedAddress);
event RemovedFromWhitelist(address indexed removedAddress);
/**
* @notice Adds an address to the whitelist.
* @param newElement the new address to add.
*/
function addToWhitelist(address newElement) external override nonReentrant() onlyOwner {
// Ignore if address is already included
if (whitelist[newElement] == Status.In) {
return;
}
// Only append new addresses to the array, never a duplicate
if (whitelist[newElement] == Status.None) {
whitelistIndices.push(newElement);
}
whitelist[newElement] = Status.In;
emit AddedToWhitelist(newElement);
}
/**
* @notice Removes an address from the whitelist.
* @param elementToRemove the existing address to remove.
*/
function removeFromWhitelist(address elementToRemove) external override nonReentrant() onlyOwner {
if (whitelist[elementToRemove] != Status.Out) {
whitelist[elementToRemove] = Status.Out;
emit RemovedFromWhitelist(elementToRemove);
}
}
/**
* @notice Checks whether an address is on the whitelist.
* @param elementToCheck the address to check.
* @return True if `elementToCheck` is on the whitelist, or False.
*/
function isOnWhitelist(address elementToCheck) external view override nonReentrantView() returns (bool) {
return whitelist[elementToCheck] == Status.In;
}
/**
* @notice Gets all addresses that are currently included in the whitelist.
* @dev Note: This method skips over, but still iterates through addresses. It is possible for this call to run out
* of gas if a large number of addresses have been removed. To reduce the likelihood of this unlikely scenario, we
* can modify the implementation so that when addresses are removed, the last addresses in the array is moved to
* the empty index.
* @return activeWhitelist the list of addresses on the whitelist.
*/
function getWhitelist() external view override nonReentrantView() returns (address[] memory activeWhitelist) {
// Determine size of whitelist first
uint256 activeCount = 0;
for (uint256 i = 0; i < whitelistIndices.length; i++) {
if (whitelist[whitelistIndices[i]] == Status.In) {
activeCount++;
}
}
// Populate whitelist
activeWhitelist = new address[](activeCount);
activeCount = 0;
for (uint256 i = 0; i < whitelistIndices.length; i++) {
address addr = whitelistIndices[i];
if (whitelist[addr] == Status.In) {
activeWhitelist[activeCount] = addr;
activeCount++;
}
}
}
}