pragma solidity ^0.8.4;
import "@openzeppelin/contracts/access/Ownable.sol";
contract Adminable is Ownable {
mapping(address => uint8) _admins;
modifier onlyAdmin() {
require(isAdmin(1), "Adminable: Not an admin with clearance level 1");
_;
}
modifier onlyAdminWithLevel(uint8 level) {
require(isAdmin(level), appendUintToString("Adminable: Not an admin with clearance level ", level));
_;
}
function isAdmin() public view returns (bool) {
return (_admins[_msgSender()] >= 1) || (owner() == _msgSender());
}
function isAdmin(uint8 level) public view returns (bool) {
return (_admins[_msgSender()] >= level) || (owner() == _msgSender());
}
function addAdmin(address admin, uint8 level) public onlyAdmin {
require(isAdmin(level), "Adminable: Cannot add admin with higher clearance level");
_admins[admin] = level;
}
function removeAdmin(address admin) public onlyAdmin {
uint8 adminRemoveLevel = _admins[admin];
require(isAdmin(adminRemoveLevel + 1), "Adminable: Cannot remove admin with higher (or the same) clearance level");
_admins[admin] = 0;
delete _admins[admin];
}
function uintToString(uint8 v) internal pure returns (string memory str) {
uint maxlength = 100;
bytes memory reversed = new bytes(maxlength);
uint i = 0;
while (v != 0) {
uint8 remainder = v % 10;
v = v / 10;
reversed[i++] = bytes1(48 + remainder);
}
bytes memory s = new bytes(i);
for (uint j = 0; j < i; j++) {
s[j] = reversed[i - 1 - j];
}
str = string(s);
}
function appendUintToString(string memory inStr, uint8 v) internal pure returns (string memory str) {
uint maxlength = 100;
bytes memory reversed = new bytes(maxlength);
uint i = 0;
while (v != 0) {
uint8 remainder = v % 10;
v = v / 10;
reversed[i++] = bytes1(48 + remainder);
}
bytes memory inStrb = bytes(inStr);
bytes memory s = new bytes(inStrb.length + i);
uint j;
for (j = 0; j < inStrb.length; j++) {
s[j] = inStrb[j];
}
for (j = 0; j < i; j++) {
s[j + inStrb.length] = reversed[i - 1 - j];
}
str = string(s);
}
}