// File: IGenArt721CoreV2.sol



// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

interface GenArt721CoreContract {
  function isWhitelisted(address sender) external view returns (bool);
  function projectIdToCurrencySymbol(uint256 _projectId) external view returns (string memory);
  function projectIdToCurrencyAddress(uint256 _projectId) external view returns (address);
  function projectIdToArtistAddress(uint256 _projectId) external view returns (address payable);
  function projectIdToPricePerTokenInWei(uint256 _projectId) external view returns (uint256);
  function projectIdToAdditionalPayee(uint256 _projectId) external view returns (address payable);
  function projectIdToAdditionalPayeePercentage(uint256 _projectId) external view returns (uint256);
  function projectTokenInfo(uint256 _projectId) external view returns (address, uint256, uint256, uint256, bool, address, uint256, string memory, address);
  function renderProviderAddress() external view returns (address payable);
  function renderProviderPercentage() external view returns (uint256);
  function mint(address _to, uint256 _projectId, address _by) external returns (uint256 tokenId);
}

// File: IValidator.sol



// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * Interface for a validation mechanism for mint destination addresses.
 */
interface Validator {
    
  /**
   * Get error message for this validator.
   */   
  function errorMessage() external view returns (string memory);

  /**
   * Validates that the given destination address is validate for a mint. Function
   * will return false if validation fails.
   */
  function validateMint(address _to) external view returns (bool);
}

// File: ValidateWhitelist.sol



// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IGenArt721CoreV2.sol";
import "./IValidator.sol";

/**
 * Validator that uses an explicit whitelist to control who
 * can receive a mint.
 */
contract ValidateWhitelist is Validator {

  GenArt721CoreContract public artblocksContract;

  string constant ErrorMessage = "address is not in the whitelist";

  mapping(address => bool) public whitelist;

  constructor(address _genArt721Address) public {
    artblocksContract = GenArt721CoreContract(_genArt721Address);
  }
  
  function batchAddToWhitelist(address[] memory _addresses) public {
    for (uint i = 0; i < _addresses.length; i++) {
      addToWhitelist(_addresses[i]);
    }
  }

  function addToWhitelist(address _address) public {
    require(artblocksContract.isWhitelisted(msg.sender), "can only be set by admin");
    whitelist[_address] = true;
  }

  function removeFromWhitelist(address _address) public {
    require(artblocksContract.isWhitelisted(msg.sender), "can only be set by admin");
    whitelist[_address] = false;
  }

  function errorMessage() external view returns (string memory) {
      return ErrorMessage;
  }

  function validateMint(address _address) external view returns(bool) {
    return whitelist[_address];
  }
}