contract Admined {
    address public owner; //named owner for etherscan compatibility
    mapping(address => uint256) public level;

    /**
     * @dev The Admined constructor sets the original `owner` of the contract to the sender
     * account and assing high level privileges.
     */
    constructor() public {
        owner = msg.sender;
        level[owner] = 3;
        emit OwnerSet(owner);
        emit LevelSet(owner, level[owner]);
    }

    /**
     * @dev Throws if called by any account with lower level than minLvl.
     * @param _minLvl Minimum level to use the function
     */
    modifier onlyAdmin(uint256 _minLvl) {
        require(level[msg.sender] >= _minLvl, 'You do not have privileges for this transaction');
        _;
    }

    /**
     * @dev Allows the current owner to transfer control of the contract to a newOwner.
     * @param newOwner The address to transfer ownership to.
     */
    function transferOwnership(address newOwner) public onlyAdmin(3) {
        require(newOwner != address(0), 'Address cannot be zero');

        owner = newOwner;
        level[owner] = 3;

        emit OwnerSet(owner);
        emit LevelSet(owner, level[owner]);

        level[msg.sender] = 0;
        emit LevelSet(msg.sender, level[msg.sender]);
    }

    /**
     * @dev Allows the assignment of new privileges to a new address.
     * @param userAddress The address to transfer ownership to.
     * @param lvl Lvl to assign.
     */
    function setLevel(address userAddress, uint256 lvl) public onlyAdmin(2) {
        require(userAddress != address(0), 'Address cannot be zero');
        require(lvl < level[msg.sender], 'You do not have privileges for this level assignment');
        require(level[msg.sender] > level[userAddress], 'You do not have privileges for this level change');

        level[userAddress] = lvl;
        emit LevelSet(userAddress, level[userAddress]);
    }

    event LevelSet(address indexed user, uint256 lvl);
    event OwnerSet(address indexed user);

}
/**
 * @title Admined
 * @dev The Admined contract has an owner address, can set administrators,
 * and provides authorization control functions. These features can be used in other contracts
 * through interfacing, so external contracts can check main contract admin levels
 */
function setLevel(address userAddress, uint256 lvl) public onlyAdmin(2) {
    require(userAddress != address(0), 'Address cannot be zero');
    require(lvl < level[msg.sender], 'You do not have privileges for this level assignment');
    require(level[msg.sender] > level[userAddress], 'You do not have privileges for this level change');

    level[userAddress] = lvl;
    emit LevelSet(userAddress, level[userAddress]);
}

/**
 * @dev Allows the assignment of new privileges to a new address.
 * @param userAddress The address to transfer ownership to.
 * @param lvl Lvl to assign.
 */