Contract Source Code:
File 1 of 1 : Validator
// File: contracts/sources/OZ/IERC20.sol
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 value) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
// File: contracts/sources/OZ/Context.sol
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
// File: contracts/sources/OZ/Ownable.sol
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
abstract contract Ownable is Context {
address private _owner;
error OwnableUnauthorizedAccount(address account);
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
// File: contracts/validator.sol
pragma solidity ^0.8.0;
contract Validator is Ownable {
address public EMLTokenAddress;
address public validatorFactory;
uint256 public validatorPrice;
address public admin;
bool public active = false;
// Validator Current Owner
mapping(address => address) public validatorOwners;
// Mapping to associate the contract address with the validator address
mapping(address => address) public validatorContracts;
// Events
event EMLBalanceChecked(uint256 balance);
event ValidatorCount(uint256 activeCount, uint256 maxCount);
event ValidatorClosed(address indexed owner, uint256 amount);
event ValidatorOpened();
event ValidatorClosedEvent();
constructor(address _EMLTokenAddress, address _initialOwner, address _validatorFactory) Ownable(_initialOwner) {
EMLTokenAddress = _EMLTokenAddress;
admin = _initialOwner;
validatorFactory = _validatorFactory; // Set the validatorFactory by default
validatorContracts[address(this)] = address(this);
validatorOwners[address(this)] = _initialOwner;
}
// Keccak hash function for an array of strings
function calculateKeccak256(string[] calldata inputs) external view returns (bytes32) {
require(active, "Validator is not active"); // Check if the validator is active
// Concatenate all strings in the array
bytes memory concatenatedString;
for (uint256 i = 0; i < inputs.length; i++) {
concatenatedString = abi.encodePacked(concatenatedString, inputs[i]);
}
// Calculate the Keccak256 hash of the concatenated string
bytes32 hash = keccak256(concatenatedString);
return hash;
}
// Set a new validator factory
function setValidatorFactory(address _validatorFactory) external onlyOwner {
require(_validatorFactory != address(0), "Invalid validator factory address");
validatorFactory = _validatorFactory;
}
// Return the validator contract address
function getValidatorContractAddress() external view returns (address) {
return validatorContracts[address(this)];
}
// Return the current validator owner
function getValidatorOwner() external view returns (address) {
return validatorOwners[address(this)];
}
// Return the amount of EML available in the contract
function getEMLBalance() external view returns (uint256) {
return IERC20(EMLTokenAddress).balanceOf(address(this));
}
// Function to close the validator and send the EML balance to the owner
function closeValidator() external onlyOwner {
uint256 balance = IERC20(EMLTokenAddress).balanceOf(address(this));
require(balance > 0, "No EML tokens to transfer");
IERC20(EMLTokenAddress).transfer(owner(), balance);
active = false;
emit ValidatorClosed(owner(), balance);
emit ValidatorClosedEvent();
}
// Open the validator if it holds at least 20,000 EML
function openValidator() external onlyOwner {
uint256 emlBalance = IERC20(EMLTokenAddress).balanceOf(address(this));
emit EMLBalanceChecked(emlBalance); // Log la balance
require(emlBalance >= 20000 * 10**18, "Validator must hold at least 20,000 EML");
active = true;
emit ValidatorOpened();
}
// Function to check if the validator is active
function isActive() external view returns (bool) {
return active;
}
// Function to get the admin address
function getAdmin() external view returns (address) {
return admin;
}
}