diff --git a/src/Summary.cpp b/src/Summary.cpp
index 2b28f98de..d780d64f5 100644
--- a/src/Summary.cpp
+++ b/src/Summary.cpp
@@ -90,10 +90,9 @@ static void print_threads(xmrig::Config *config)
             snprintf(buf, sizeof buf, ", affinity=0x%" PRIX64, config->affinity());
         }
 
-        xmrig::Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%d") WHITE_BOLD(", %s, av=%d, %sdonate=%d%%") WHITE_BOLD("%s"),
+        xmrig::Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%d") WHITE_BOLD(", av=%d, %sdonate=%d%%") WHITE_BOLD("%s"),
                           "THREADS",
                           config->threadsCount(),
-                          config->algorithm().shortName(),
                           config->algoVariant(),
                           config->pools().donateLevel() == 0 ? RED_BOLD_S : "",
                           config->pools().donateLevel(),
@@ -101,10 +100,9 @@ static void print_threads(xmrig::Config *config)
                           );
     }
     else {
-        xmrig::Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%d") WHITE_BOLD(", %s, %sdonate=%d%%"),
+        xmrig::Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%d") WHITE_BOLD(", %sdonate=%d%%"),
                           "THREADS",
                           config->threadsCount(),
-                          config->algorithm().shortName(),
                           config->pools().donateLevel() == 0 ? RED_BOLD_S : "",
                           config->pools().donateLevel()
                           );
diff --git a/src/base/kernel/config/BaseConfig.cpp b/src/base/kernel/config/BaseConfig.cpp
index af2418aa2..489849a38 100644
--- a/src/base/kernel/config/BaseConfig.cpp
+++ b/src/base/kernel/config/BaseConfig.cpp
@@ -60,14 +60,7 @@
 #include "version.h"
 
 
-xmrig::BaseConfig::BaseConfig() :
-    m_algorithm(CRYPTONIGHT, VARIANT_AUTO),
-    m_autoSave(true),
-    m_background(false),
-    m_dryRun(false),
-    m_syslog(false),
-    m_upgrade(false),
-    m_watch(true)
+xmrig::BaseConfig::BaseConfig()
 {
 }
 
@@ -160,19 +153,7 @@ bool xmrig::BaseConfig::read(const IJsonReader &reader, const char *fileName)
     m_http.load(chain.getObject("http"));
 #   endif
 
-    m_algorithm.parseAlgorithm(reader.getString("algo", "cn"));
-
-    m_pools.load(reader.getArray("pools"));
-    m_pools.setDonateLevel(reader.getInt("donate-level", kDefaultDonateLevel));
-    m_pools.setProxyDonate(reader.getInt("donate-over-proxy", Pools::PROXY_DONATE_AUTO));
-    m_pools.setRetries(reader.getInt("retries"));
-    m_pools.setRetryPause(reader.getInt("retry-pause"));
-
-    if (!m_algorithm.isValid()) {
-        return false;
-    }
-
-    m_pools.adjust(m_algorithm);
+    m_pools.load(reader);
 
     return m_pools.active() > 0;
 }
diff --git a/src/base/kernel/config/BaseConfig.h b/src/base/kernel/config/BaseConfig.h
index f0c52536e..48d7c2cfc 100644
--- a/src/base/kernel/config/BaseConfig.h
+++ b/src/base/kernel/config/BaseConfig.h
@@ -59,7 +59,6 @@ public:
     inline uint32_t printTime() const              { return m_printTime; }
 
     inline bool isWatch() const override                   { return m_watch && !m_fileName.isNull(); }
-    inline const Algorithm &algorithm() const override     { return m_algorithm; }
     inline const String &fileName() const override         { return m_fileName; }
     inline void setFileName(const char *fileName) override { m_fileName = fileName; }
 
@@ -69,13 +68,12 @@ public:
     void printVersions();
 
 protected:
-    Algorithm m_algorithm;
-    bool m_autoSave;
-    bool m_background;
-    bool m_dryRun;
-    bool m_syslog;
-    bool m_upgrade;
-    bool m_watch;
+    bool m_autoSave    = true;
+    bool m_background  = false;
+    bool m_dryRun      = false;
+    bool m_syslog      = false;
+    bool m_upgrade     = false;
+    bool m_watch       = true;
     Http m_http;
     Pools m_pools;
     String m_apiId;
diff --git a/src/base/kernel/interfaces/IConfig.h b/src/base/kernel/interfaces/IConfig.h
index 3d0407e65..c8189ba58 100644
--- a/src/base/kernel/interfaces/IConfig.h
+++ b/src/base/kernel/interfaces/IConfig.h
@@ -144,7 +144,6 @@ public:
     virtual bool isWatch() const                                       = 0;
     virtual bool read(const IJsonReader &reader, const char *fileName) = 0;
     virtual bool save()                                                = 0;
-    virtual const Algorithm &algorithm() const                         = 0;
     virtual const String &fileName() const                             = 0;
     virtual void getJSON(rapidjson::Document &doc) const               = 0;
     virtual void setFileName(const char *fileName)                     = 0;
diff --git a/src/base/net/stratum/Client.cpp b/src/base/net/stratum/Client.cpp
index 1d448ddff..05e53c784 100644
--- a/src/base/net/stratum/Client.cpp
+++ b/src/base/net/stratum/Client.cpp
@@ -333,17 +333,6 @@ bool xmrig::Client::parseJob(const rapidjson::Value &params, int *code)
         job.setAlgorithm(params["algo"].GetString());
     }
 
-    if (params.HasMember("variant")) {
-        const rapidjson::Value &variant = params["variant"];
-
-        if (variant.IsInt()) {
-            job.setVariant(variant.GetInt());
-        }
-        else if (variant.IsString()){
-            job.setVariant(variant.GetString());
-        }
-    }
-
     if (params.HasMember("height")) {
         const rapidjson::Value &variant = params["height"];
 
@@ -438,7 +427,7 @@ bool xmrig::Client::verifyAlgorithm(const Algorithm &algorithm) const
     }
 #   endif
 
-    if (m_pool.isCompatible(algorithm)) {
+    if (m_pool.algorithm() == algorithm) { // FIXME
         return true;
     }
 
@@ -590,18 +579,18 @@ void xmrig::Client::login()
         params.AddMember("rigid", m_pool.rigId().toJSON(), allocator);
     }
 
-#   ifdef XMRIG_PROXY_PROJECT
-    if (m_pool.algorithm().variant() != xmrig::VARIANT_AUTO)
-#   endif
-    {
-        Value algo(kArrayType);
+//#   ifdef XMRIG_PROXY_PROJECT FIXME
+//    if (m_pool.algorithm().variant() != xmrig::VARIANT_AUTO)
+//#   endif
+//    {
+//        Value algo(kArrayType);
 
-        for (const auto &a : m_pool.algorithms()) {
-            algo.PushBack(StringRef(a.shortName()), allocator);
-        }
+//        for (const auto &a : m_pool.algorithms()) {
+//            algo.PushBack(StringRef(a.shortName()), allocator);
+//        }
 
-        params.AddMember("algo", algo, allocator);
-    }
+//        params.AddMember("algo", algo, allocator);
+//    }
 
     m_listener->onLogin(this, doc, params);
 
diff --git a/src/base/net/stratum/Job.cpp b/src/base/net/stratum/Job.cpp
index 1f1cd4139..293d0f46c 100644
--- a/src/base/net/stratum/Job.cpp
+++ b/src/base/net/stratum/Job.cpp
@@ -34,10 +34,8 @@
 
 
 xmrig::Job::Job() :
-    m_autoVariant(false),
     m_nicehash(false),
     m_poolId(-2),
-    m_threadId(-1),
     m_size(0),
     m_diff(0),
     m_height(0),
@@ -49,10 +47,8 @@ xmrig::Job::Job() :
 
 xmrig::Job::Job(int poolId, bool nicehash, const Algorithm &algorithm, const String &clientId) :
     m_algorithm(algorithm),
-    m_autoVariant(algorithm.variant() == VARIANT_AUTO),
     m_nicehash(nicehash),
     m_poolId(poolId),
-    m_threadId(-1),
     m_size(0),
     m_clientId(clientId),
     m_diff(0),
@@ -98,10 +94,6 @@ bool xmrig::Job::setBlob(const char *blob)
         m_nicehash = true;
     }
 
-    if (m_autoVariant) {
-        m_algorithm.setVariant(variant());
-    }
-
 #   ifdef XMRIG_PROXY_PROJECT
     memset(m_rawBlob, 0, sizeof(m_rawBlob));
     memcpy(m_rawBlob, blob, m_size * 2);
@@ -153,16 +145,6 @@ bool xmrig::Job::setTarget(const char *target)
 }
 
 
-void xmrig::Job::setAlgorithm(const char *algo)
-{
-    m_algorithm.parseAlgorithm(algo);
-
-    if (m_algorithm.variant() == xmrig::VARIANT_AUTO) {
-        m_algorithm.setVariant(variant());
-    }
-}
-
-
 void xmrig::Job::setDiff(uint64_t diff)
 {
     m_diff   = diff;
@@ -173,23 +155,3 @@ void xmrig::Job::setDiff(uint64_t diff)
     m_rawTarget[16] = '\0';
 #   endif
 }
-
-
-xmrig::Variant xmrig::Job::variant() const
-{
-    switch (m_algorithm.algo()) {
-    case CRYPTONIGHT:
-        return (m_blob[0] >= 10) ? VARIANT_4 : ((m_blob[0] >= 8) ? VARIANT_2 : VARIANT_1);
-
-    case CRYPTONIGHT_LITE:
-        return VARIANT_1;
-
-    case CRYPTONIGHT_HEAVY:
-        return VARIANT_0;
-
-    default:
-        break;
-    }
-
-    return m_algorithm.variant();
-}
diff --git a/src/base/net/stratum/Job.h b/src/base/net/stratum/Job.h
index 5052040a5..518a337e8 100644
--- a/src/base/net/stratum/Job.h
+++ b/src/base/net/stratum/Job.h
@@ -53,7 +53,6 @@ public:
     bool isEqual(const Job &other) const;
     bool setBlob(const char *blob);
     bool setTarget(const char *target);
-    void setAlgorithm(const char *algo);
     void setDiff(uint64_t diff);
 
     inline bool isNicehash() const                    { return m_nicehash; }
@@ -65,7 +64,6 @@ public:
     inline const uint32_t *nonce() const              { return reinterpret_cast<const uint32_t*>(m_blob + 39); }
     inline const uint8_t *blob() const                { return m_blob; }
     inline int poolId() const                         { return m_poolId; }
-    inline int threadId() const                       { return m_threadId; }
     inline size_t size() const                        { return m_size; }
     inline uint32_t *nonce()                          { return reinterpret_cast<uint32_t*>(m_blob + 39); }
     inline uint64_t diff() const                      { return m_diff; }
@@ -73,12 +71,10 @@ public:
     inline uint64_t target() const                    { return m_target; }
     inline uint8_t fixedByte() const                  { return *(m_blob + 42); }
     inline void reset()                               { m_size = 0; m_diff = 0; }
+    inline void setAlgorithm(const char *algo)        { m_algorithm = algo; }
     inline void setClientId(const String &id)         { m_clientId = id; }
     inline void setHeight(uint64_t height)            { m_height = height; }
     inline void setPoolId(int poolId)                 { m_poolId = poolId; }
-    inline void setThreadId(int threadId)             { m_threadId = threadId; }
-    inline void setVariant(const char *variant)       { m_algorithm.parseVariant(variant); }
-    inline void setVariant(int variant)               { m_algorithm.parseVariant(variant); }
 
 #   ifdef XMRIG_PROXY_PROJECT
     inline char *rawBlob()                 { return m_rawBlob; }
@@ -93,13 +89,9 @@ public:
     inline bool operator!=(const Job &other) const { return !isEqual(other); }
 
 private:
-    Variant variant() const;
-
     Algorithm m_algorithm;
-    bool m_autoVariant;
     bool m_nicehash;
     int m_poolId;
-    int m_threadId;
     size_t m_size;
     String m_clientId;
     String m_id;
diff --git a/src/base/net/stratum/Pool.cpp b/src/base/net/stratum/Pool.cpp
index f441ba636..bb3fab72c 100644
--- a/src/base/net/stratum/Pool.cpp
+++ b/src/base/net/stratum/Pool.cpp
@@ -47,6 +47,7 @@
 
 namespace xmrig {
 
+static const char *kAlgo                   = "algo";
 static const char *kDaemon                 = "daemon";
 static const char *kDaemonPollInterval     = "daemon-poll-interval";
 static const char *kEnabled                = "enabled";
@@ -58,7 +59,6 @@ static const char *kRigId                  = "rig-id";
 static const char *kTls                    = "tls";
 static const char *kUrl                    = "url";
 static const char *kUser                   = "user";
-static const char *kVariant                = "variant";
 
 const String Pool::kDefaultPassword        = "x";
 const String Pool::kDefaultUser            = "x";
@@ -119,6 +119,7 @@ xmrig::Pool::Pool(const rapidjson::Value &object) :
     m_rigId        = Json::getString(object, kRigId);
     m_fingerprint  = Json::getString(object, kFingerprint);
     m_pollInterval = Json::getUint64(object, kDaemonPollInterval, kDefaultPollInterval);
+    m_algorithm    = Json::getString(object, kAlgo);
 
     m_flags.set(FLAG_ENABLED,  Json::getBool(object, kEnabled, true));
     m_flags.set(FLAG_NICEHASH, Json::getBool(object, kNicehash));
@@ -132,15 +133,6 @@ xmrig::Pool::Pool(const rapidjson::Value &object) :
     else if (keepalive.IsBool()) {
         setKeepAlive(keepalive.GetBool());
     }
-
-    const rapidjson::Value &variant = Json::getValue(object, kVariant);
-    if (variant.IsString()) {
-        algorithm().parseVariant(variant.GetString());
-    }
-    else if (variant.IsInt()) {
-        algorithm().parseVariant(variant.GetInt());
-    }
-
 }
 
 
@@ -166,28 +158,6 @@ xmrig::Pool::Pool(const char *host, uint16_t port, const char *user, const char
 }
 
 
-bool xmrig::Pool::isCompatible(const Algorithm &algorithm) const
-{
-    if (m_algorithms.empty()) {
-        return true;
-    }
-
-    for (const auto &a : m_algorithms) {
-        if (algorithm == a) {
-            return true;
-        }
-    }
-
-#   ifdef XMRIG_PROXY_PROJECT
-    if (m_algorithm.algo() == xmrig::CRYPTONIGHT && algorithm.algo() == xmrig::CRYPTONIGHT) {
-        return m_algorithm.variant() == xmrig::VARIANT_RWZ || m_algorithm.variant() == xmrig::VARIANT_ZLS;
-    }
-#   endif
-
-    return false;
-}
-
-
 bool xmrig::Pool::isEnabled() const
 {
 #   ifndef XMRIG_FEATURE_TLS
@@ -289,6 +259,7 @@ rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const
 
     Value obj(kObjectType);
 
+    obj.AddMember(StringRef(kAlgo),  StringRef(m_algorithm.shortName()), allocator);
     obj.AddMember(StringRef(kUrl),   m_url.toJSON(), allocator);
     obj.AddMember(StringRef(kUser),  m_user.toJSON(), allocator);
     obj.AddMember(StringRef(kPass),  m_password.toJSON(), allocator);
@@ -305,22 +276,6 @@ rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const
         obj.AddMember(StringRef(kKeepalive), m_keepAlive, allocator);
     }
 
-    switch (m_algorithm.variant()) {
-    case VARIANT_AUTO:
-    case VARIANT_0:
-    case VARIANT_1:
-        obj.AddMember(StringRef(kVariant), m_algorithm.variant(), allocator);
-        break;
-
-    case VARIANT_2:
-        obj.AddMember(StringRef(kVariant), 2, allocator);
-        break;
-
-    default:
-        obj.AddMember(StringRef(kVariant), StringRef(m_algorithm.variantName()), allocator);
-        break;
-    }
-
     obj.AddMember(StringRef(kEnabled),            m_flags.test(FLAG_ENABLED), allocator);
     obj.AddMember(StringRef(kTls),                isTLS(), allocator);
     obj.AddMember(StringRef(kFingerprint),        m_fingerprint.toJSON(), allocator);
@@ -331,29 +286,6 @@ rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const
 }
 
 
-void xmrig::Pool::adjust(const Algorithm &algorithm)
-{
-    if (!isValid()) {
-        return;
-    }
-
-    if (!m_algorithm.isValid()) {
-        m_algorithm.setAlgo(algorithm.algo());
-        adjustVariant(algorithm.variant());
-    }
-
-    rebuild();
-}
-
-
-void xmrig::Pool::setAlgo(const xmrig::Algorithm &algorithm)
-{
-    m_algorithm = algorithm;
-
-    rebuild();
-}
-
-
 #ifdef APP_DEBUG
 void xmrig::Pool::print() const
 {
@@ -391,132 +323,3 @@ bool xmrig::Pool::parseIPv6(const char *addr)
 
     return true;
 }
-
-
-void xmrig::Pool::addVariant(xmrig::Variant variant)
-{
-    const xmrig::Algorithm algorithm(m_algorithm.algo(), variant);
-    if (!algorithm.isValid() || m_algorithm == algorithm) {
-        return;
-    }
-
-    m_algorithms.push_back(algorithm);
-}
-
-
-void xmrig::Pool::adjustVariant(const xmrig::Variant variantHint)
-{
-#   ifndef XMRIG_PROXY_PROJECT
-    using namespace xmrig;
-
-    if (m_host.contains(".nicehash.com")) {
-        m_flags.set(FLAG_NICEHASH, true);
-        m_keepAlive = false;
-        bool valid  = true;
-
-        switch (m_port) {
-        case 3355:
-        case 33355:
-            valid = m_algorithm.algo() == CRYPTONIGHT && m_host.contains("cryptonight.");
-            m_algorithm.setVariant(VARIANT_0);
-            break;
-
-        case 3363:
-        case 33363:
-            valid = m_algorithm.algo() == CRYPTONIGHT && m_host.contains("cryptonightv7.");
-            m_algorithm.setVariant(VARIANT_1);
-            break;
-
-        case 3364:
-            valid = m_algorithm.algo() == CRYPTONIGHT_HEAVY && m_host.contains("cryptonightheavy.");
-            m_algorithm.setVariant(VARIANT_0);
-            break;
-
-        case 3367:
-        case 33367:
-            valid = m_algorithm.algo() == CRYPTONIGHT && m_host.contains("cryptonightv8.");
-            m_algorithm.setVariant(VARIANT_2);
-            break;
-
-        default:
-            break;
-        }
-
-        if (!valid) {
-            m_algorithm.setAlgo(INVALID_ALGO);
-        }
-
-        m_flags.set(FLAG_TLS, m_port > 33000);
-        return;
-    }
-
-    if (m_host.contains(".minergate.com")) {
-        m_keepAlive = false;
-        bool valid  = true;
-        m_algorithm.setVariant(VARIANT_1);
-
-        if (m_host.contains("xmr.pool.")) {
-            valid = m_algorithm.algo() == CRYPTONIGHT;
-            m_algorithm.setVariant(m_port == 45700 ? VARIANT_AUTO : VARIANT_0);
-        }
-        else if (m_host.contains("aeon.pool.") && m_port == 45690) {
-            valid = m_algorithm.algo() == CRYPTONIGHT_LITE;
-            m_algorithm.setVariant(VARIANT_1);
-        }
-
-        if (!valid) {
-            m_algorithm.setAlgo(INVALID_ALGO);
-        }
-
-        return;
-    }
-
-    if (variantHint != VARIANT_AUTO) {
-        m_algorithm.setVariant(variantHint);
-        return;
-    }
-
-    if (m_algorithm.variant() != VARIANT_AUTO) {
-        return;
-    }
-
-    if (m_algorithm.algo() == CRYPTONIGHT_HEAVY)  {
-        m_algorithm.setVariant(VARIANT_0);
-    }
-    else if (m_algorithm.algo() == CRYPTONIGHT_LITE) {
-        m_algorithm.setVariant(VARIANT_1);
-    }
-#   endif
-}
-
-
-void xmrig::Pool::rebuild()
-{
-    m_algorithms.clear();
-
-    if (!m_algorithm.isValid()) {
-        return;
-    }
-
-    m_algorithms.push_back(m_algorithm);
-
-#   ifndef XMRIG_PROXY_PROJECT
-    addVariant(VARIANT_4);
-    addVariant(VARIANT_WOW);
-    addVariant(VARIANT_2);
-    addVariant(VARIANT_1);
-    addVariant(VARIANT_0);
-    addVariant(VARIANT_HALF);
-    addVariant(VARIANT_XTL);
-    addVariant(VARIANT_TUBE);
-    addVariant(VARIANT_MSR);
-    addVariant(VARIANT_XHV);
-    addVariant(VARIANT_XAO);
-    addVariant(VARIANT_RTO);
-    addVariant(VARIANT_GPU);
-    addVariant(VARIANT_RWZ);
-    addVariant(VARIANT_ZLS);
-    addVariant(VARIANT_DOUBLE);
-    addVariant(VARIANT_AUTO);
-#   endif
-}
diff --git a/src/base/net/stratum/Pool.h b/src/base/net/stratum/Pool.h
index 5348271ac..36c3ed1b5 100644
--- a/src/base/net/stratum/Pool.h
+++ b/src/base/net/stratum/Pool.h
@@ -69,13 +69,11 @@ public:
          bool tls               = false
        );
 
-    inline Algorithm &algorithm()                       { return m_algorithm; }
     inline bool isDaemon() const                        { return m_flags.test(FLAG_DAEMON); }
     inline bool isNicehash() const                      { return m_flags.test(FLAG_NICEHASH); }
     inline bool isTLS() const                           { return m_flags.test(FLAG_TLS); }
     inline bool isValid() const                         { return !m_host.isNull() && m_port > 0; }
     inline const Algorithm &algorithm() const           { return m_algorithm; }
-    inline const Algorithms &algorithms() const         { return m_algorithms; }
     inline const String &fingerprint() const            { return m_fingerprint; }
     inline const String &host() const                   { return m_host; }
     inline const String &password() const               { return !m_password.isNull() ? m_password : kDefaultPassword; }
@@ -85,6 +83,7 @@ public:
     inline int keepAlive() const                        { return m_keepAlive; }
     inline uint16_t port() const                        { return m_port; }
     inline uint64_t pollInterval() const                { return m_pollInterval; }
+    inline void setAlgo(const Algorithm &algorithm)     { m_algorithm = algorithm; }
     inline void setPassword(const String &password)     { m_password = password; }
     inline void setRigId(const String &rigId)           { m_rigId = rigId; }
     inline void setUser(const String &user)             { m_user = user; }
@@ -92,13 +91,10 @@ public:
     inline bool operator!=(const Pool &other) const     { return !isEqual(other); }
     inline bool operator==(const Pool &other) const     { return isEqual(other); }
 
-    bool isCompatible(const Algorithm &algorithm) const;
     bool isEnabled() const;
     bool isEqual(const Pool &other) const;
     bool parse(const char *url);
     rapidjson::Value toJSON(rapidjson::Document &doc) const;
-    void adjust(const Algorithm &algorithm);
-    void setAlgo(const Algorithm &algorithm);
 
 #   ifdef APP_DEBUG
     void print() const;
@@ -109,12 +105,8 @@ private:
     inline void setKeepAlive(int keepAlive)             { m_keepAlive = keepAlive >= 0 ? keepAlive : 0; }
 
     bool parseIPv6(const char *addr);
-    void addVariant(Variant variant);
-    void adjustVariant(const Variant variantHint);
-    void rebuild();
 
     Algorithm m_algorithm;
-    Algorithms m_algorithms;
     int m_keepAlive;
     std::bitset<FLAG_MAX> m_flags;
     String m_fingerprint;
diff --git a/src/base/net/stratum/Pools.cpp b/src/base/net/stratum/Pools.cpp
index 638ba5ea7..985e5d4ec 100644
--- a/src/base/net/stratum/Pools.cpp
+++ b/src/base/net/stratum/Pools.cpp
@@ -24,6 +24,7 @@
 
 
 #include "base/io/log/Log.h"
+#include "base/kernel/interfaces/IJsonReader.h"
 #include "base/net/stratum/Pools.h"
 #include "base/net/stratum/strategies/FailoverStrategy.h"
 #include "base/net/stratum/strategies/SinglePoolStrategy.h"
@@ -103,18 +104,11 @@ size_t xmrig::Pools::active() const
 }
 
 
-void xmrig::Pools::adjust(const Algorithm &algorithm)
-{
-    for (Pool &pool : m_data) {
-        pool.adjust(algorithm);
-    }
-}
-
-
-void xmrig::Pools::load(const rapidjson::Value &pools)
+void xmrig::Pools::load(const IJsonReader &reader)
 {
     m_data.clear();
 
+    const rapidjson::Value &pools = reader.getArray("pools");
     if (!pools.IsArray()) {
         return;
     }
@@ -129,6 +123,11 @@ void xmrig::Pools::load(const rapidjson::Value &pools)
             m_data.push_back(std::move(pool));
         }
     }
+
+    setDonateLevel(reader.getInt("donate-level", kDefaultDonateLevel));
+    setProxyDonate(reader.getInt("donate-over-proxy", PROXY_DONATE_AUTO));
+    setRetries(reader.getInt("retries"));
+    setRetryPause(reader.getInt("retry-pause"));
 }
 
 
@@ -136,11 +135,11 @@ void xmrig::Pools::print() const
 {
     size_t i = 1;
     for (const Pool &pool : m_data) {
-        Log::print(GREEN_BOLD(" * ") WHITE_BOLD("POOL #%-7zu") CSI "1;%dm%s" CLEAR " variant " WHITE_BOLD("%s"),
+        Log::print(GREEN_BOLD(" * ") WHITE_BOLD("POOL #%-7zu") CSI "1;%dm%s" CLEAR " algo " WHITE_BOLD("%s"),
                    i,
                    (pool.isEnabled() ? (pool.isTLS() ? 32 : 36) : 31),
                    pool.url().data(),
-                   pool.algorithm().variantName()
+                   pool.algorithm().shortName()
                    );
 
         i++;
diff --git a/src/base/net/stratum/Pools.h b/src/base/net/stratum/Pools.h
index 6a63f166b..70e172255 100644
--- a/src/base/net/stratum/Pools.h
+++ b/src/base/net/stratum/Pools.h
@@ -35,6 +35,7 @@
 namespace xmrig {
 
 
+class IJsonReader;
 class IStrategy;
 class IStrategyListener;
 
@@ -63,15 +64,15 @@ public:
     IStrategy *createStrategy(IStrategyListener *listener) const;
     rapidjson::Value toJSON(rapidjson::Document &doc) const;
     size_t active() const;
-    void adjust(const Algorithm &algorithm);
-    void load(const rapidjson::Value &pools);
+    void load(const IJsonReader &reader);
     void print() const;
+
+private:
     void setDonateLevel(int level);
     void setProxyDonate(int value);
     void setRetries(int retries);
     void setRetryPause(int retryPause);
 
-private:
     int m_donateLevel;
     int m_retries;
     int m_retryPause;
diff --git a/src/core/config/Config.cpp b/src/core/config/Config.cpp
index c1430e4d5..fbb12ffa7 100644
--- a/src/core/config/Config.cpp
+++ b/src/core/config/Config.cpp
@@ -87,8 +87,6 @@ void xmrig::Config::getJSON(rapidjson::Document &doc) const
 
     auto &allocator = doc.GetAllocator();
 
-    doc.AddMember("algo", StringRef(algorithm().name()), allocator);
-
     Value api(kObjectType);
     api.AddMember("id",           m_apiId.toJSON(), allocator);
     api.AddMember("worker-id",    m_apiWorkerId.toJSON(), allocator);
@@ -146,37 +144,37 @@ void xmrig::Config::getJSON(rapidjson::Document &doc) const
 
 bool xmrig::Config::finalize()
 {
-    if (!m_threads.cpu.empty()) {
-        m_threads.mode     = Advanced;
-        const bool softAES = (m_aesMode == AES_AUTO ? (Cpu::info()->hasAES() ? AES_HW : AES_SOFT) : m_aesMode) == AES_SOFT;
+//    if (!m_threads.cpu.empty()) { // FIXME
+//        m_threads.mode     = Advanced;
+//        const bool softAES = (m_aesMode == AES_AUTO ? (Cpu::info()->hasAES() ? AES_HW : AES_SOFT) : m_aesMode) == AES_SOFT;
 
-        for (size_t i = 0; i < m_threads.cpu.size(); ++i) {
-            m_threads.list.push_back(CpuThread::createFromData(i, m_algorithm.algo(), m_threads.cpu[i], m_priority, softAES));
-        }
+//        for (size_t i = 0; i < m_threads.cpu.size(); ++i) {
+////            m_threads.list.push_back(CpuThread::createFromData(i, m_algorithm.algo(), m_threads.cpu[i], m_priority, softAES));
+//        }
 
-        return true;
-    }
+//        return true;
+//    }
 
-    const AlgoVariant av = getAlgoVariant();
-    m_threads.mode = m_threads.count ? Simple : Automatic;
+//    const AlgoVariant av = getAlgoVariant();
+//    m_threads.mode = m_threads.count ? Simple : Automatic;
 
-    const size_t size = CpuThread::multiway(av) * cn_select_memory(m_algorithm.algo()) / 1024;
+////    const size_t size = CpuThread::multiway(av) * cn_select_memory(m_algorithm.algo()) / 1024;
 
-    if (!m_threads.count) {
-        m_threads.count = Cpu::info()->optimalThreadsCount(size, m_maxCpuUsage);
-    }
-    else if (m_safe) {
-        const size_t count = Cpu::info()->optimalThreadsCount(size, m_maxCpuUsage);
-        if (m_threads.count > count) {
-            m_threads.count = count;
-        }
-    }
+//    if (!m_threads.count) {
+//        m_threads.count = Cpu::info()->optimalThreadsCount(size, m_maxCpuUsage);
+//    }
+//    else if (m_safe) {
+//        const size_t count = Cpu::info()->optimalThreadsCount(size, m_maxCpuUsage);
+//        if (m_threads.count > count) {
+//            m_threads.count = count;
+//        }
+//    }
 
-    for (size_t i = 0; i < m_threads.count; ++i) {
-        m_threads.list.push_back(CpuThread::createFromAV(i, m_algorithm.algo(), av, m_threads.mask, m_priority, m_assembly));
-    }
+//    for (size_t i = 0; i < m_threads.count; ++i) {
+//        m_threads.list.push_back(CpuThread::createFromAV(i, m_algorithm.algo(), av, m_threads.mask, m_priority, m_assembly));
+//    }
 
-    m_shouldSave = m_threads.mode == Automatic;
+//    m_shouldSave = m_threads.mode == Automatic;
 
     return true;
 }
@@ -245,9 +243,9 @@ void xmrig::Config::setThreads(const rapidjson::Value &threads)
 xmrig::AlgoVariant xmrig::Config::getAlgoVariant() const
 {
 #   ifdef XMRIG_ALGO_CN_LITE
-    if (m_algorithm.algo() == xmrig::CRYPTONIGHT_LITE) {
-        return getAlgoVariantLite();
-    }
+//    if (m_algorithm.algo() == xmrig::CRYPTONIGHT_LITE) { // FIXME
+//        return getAlgoVariantLite();
+//    }
 #   endif
 
     if (m_algoVariant <= AV_AUTO || m_algoVariant >= AV_MAX) {
diff --git a/src/crypto/common/Algorithm.cpp b/src/crypto/common/Algorithm.cpp
index 29ca9ecfe..f85b0a6f3 100644
--- a/src/crypto/common/Algorithm.cpp
+++ b/src/crypto/common/Algorithm.cpp
@@ -44,254 +44,96 @@
 #endif
 
 
-struct AlgoData
+namespace xmrig {
+
+
+struct AlgoName
 {
     const char *name;
     const char *shortName;
-    xmrig::Algo algo;
-    xmrig::Variant variant;
+    const Algorithm::Id id;
 };
 
 
-static AlgoData const algorithms[] = {
-    { "cryptonight",           "cn",           xmrig::CRYPTONIGHT,       xmrig::VARIANT_AUTO   },
-    { "cryptonight/0",         "cn/0",         xmrig::CRYPTONIGHT,       xmrig::VARIANT_0      },
-    { "cryptonight/1",         "cn/1",         xmrig::CRYPTONIGHT,       xmrig::VARIANT_1      },
-    { "cryptonight/xtl",       "cn/xtl",       xmrig::CRYPTONIGHT,       xmrig::VARIANT_XTL    },
-    { "cryptonight/msr",       "cn/msr",       xmrig::CRYPTONIGHT,       xmrig::VARIANT_MSR    },
-    { "cryptonight/xao",       "cn/xao",       xmrig::CRYPTONIGHT,       xmrig::VARIANT_XAO    },
-    { "cryptonight/rto",       "cn/rto",       xmrig::CRYPTONIGHT,       xmrig::VARIANT_RTO    },
-    { "cryptonight/2",         "cn/2",         xmrig::CRYPTONIGHT,       xmrig::VARIANT_2      },
-    { "cryptonight/half",      "cn/half",      xmrig::CRYPTONIGHT,       xmrig::VARIANT_HALF   },
-    { "cryptonight/xtlv9",     "cn/xtlv9",     xmrig::CRYPTONIGHT,       xmrig::VARIANT_HALF   },
-    { "cryptonight/wow",       "cn/wow",       xmrig::CRYPTONIGHT,       xmrig::VARIANT_WOW    },
-    { "cryptonight/r",         "cn/r",         xmrig::CRYPTONIGHT,       xmrig::VARIANT_4      },
-    { "cryptonight/rwz",       "cn/rwz",       xmrig::CRYPTONIGHT,       xmrig::VARIANT_RWZ    },
-    { "cryptonight/zls",       "cn/zls",       xmrig::CRYPTONIGHT,       xmrig::VARIANT_ZLS    },
-    { "cryptonight/double",    "cn/double",    xmrig::CRYPTONIGHT,       xmrig::VARIANT_DOUBLE },
-
-#   ifdef XMRIG_ALGO_CN_LITE
-    { "cryptonight-lite",      "cn-lite",      xmrig::CRYPTONIGHT_LITE,  xmrig::VARIANT_AUTO },
-    { "cryptonight-light",     "cn-light",     xmrig::CRYPTONIGHT_LITE,  xmrig::VARIANT_AUTO },
-    { "cryptonight-lite/0",    "cn-lite/0",    xmrig::CRYPTONIGHT_LITE,  xmrig::VARIANT_0    },
-    { "cryptonight-lite/1",    "cn-lite/1",    xmrig::CRYPTONIGHT_LITE,  xmrig::VARIANT_1    },
-#   endif
-
-#   ifdef XMRIG_ALGO_CN_HEAVY
-    { "cryptonight-heavy",      "cn-heavy",      xmrig::CRYPTONIGHT_HEAVY, xmrig::VARIANT_AUTO },
-    { "cryptonight-heavy/0",    "cn-heavy/0",    xmrig::CRYPTONIGHT_HEAVY, xmrig::VARIANT_0    },
-    { "cryptonight-heavy/xhv",  "cn-heavy/xhv",  xmrig::CRYPTONIGHT_HEAVY, xmrig::VARIANT_XHV  },
-    { "cryptonight-heavy/tube", "cn-heavy/tube", xmrig::CRYPTONIGHT_HEAVY, xmrig::VARIANT_TUBE },
-#   endif
-
-#   ifdef XMRIG_ALGO_CN_PICO
-    { "cryptonight-pico/trtl",  "cn-pico/trtl",  xmrig::CRYPTONIGHT_PICO, xmrig::VARIANT_TRTL },
-    { "cryptonight-pico",       "cn-pico",       xmrig::CRYPTONIGHT_PICO, xmrig::VARIANT_TRTL },
-    { "cryptonight-turtle",     "cn-trtl",       xmrig::CRYPTONIGHT_PICO, xmrig::VARIANT_TRTL },
-    { "cryptonight-ultralite",  "cn-ultralite",  xmrig::CRYPTONIGHT_PICO, xmrig::VARIANT_TRTL },
-    { "cryptonight_turtle",     "cn_turtle",     xmrig::CRYPTONIGHT_PICO, xmrig::VARIANT_TRTL },
-#   endif
-
+static AlgoName const algorithm_names[] = {
+    { "cryptonight/0",            "cn/0",              Algorithm::CN_0            },
+    { "cryptonight",              "cn",                Algorithm::CN_0            },
+    { "cryptonight/1",            "cn/1",              Algorithm::CN_1            },
+    { "cryptonight-monerov7",     nullptr,             Algorithm::CN_1            },
+    { "cryptonight_v7",           nullptr,             Algorithm::CN_1            },
+    { "cryptonight/2",            "cn/2",              Algorithm::CN_2            },
+    { "cryptonight-monerov8",      nullptr,            Algorithm::CN_2            },
+    { "cryptonight_v8",            nullptr,            Algorithm::CN_2            },
+    { "cryptonight/r",             "cn/r",             Algorithm::CN_R            },
+    { "cryptonight_r",             nullptr,            Algorithm::CN_R            },
+    { "cryptonight/wow",           "cn/wow",           Algorithm::CN_WOW          },
+    { "cryptonight/fast",          "cn/fast",          Algorithm::CN_FAST         },
+    { "cryptonight/msr",           "cn/msr",           Algorithm::CN_FAST         },
+    { "cryptonight/half",          "cn/half",          Algorithm::CN_HALF         },
+    { "cryptonight/xao",           "cn/xao",           Algorithm::CN_XAO          },
+    { "cryptonight_alloy",         nullptr,            Algorithm::CN_XAO          },
+    { "cryptonight/rto",           "cn/rto",           Algorithm::CN_RTO          },
+    { "cryptonight/rwz",           "cn/rwz",           Algorithm::CN_RWZ          },
+    { "cryptonight/zls",           "cn/zls",           Algorithm::CN_ZLS          },
+    { "cryptonight/double",        "cn/double",        Algorithm::CN_ZLS          },
 #   ifdef XMRIG_ALGO_CN_GPU
-    { "cryptonight/gpu",        "cn/gpu",  xmrig::CRYPTONIGHT, xmrig::VARIANT_GPU },
+    { "cryptonight/gpu",           "cn/gpu",           Algorithm::CN_GPU          },
+    { "cryptonight_gpu",           nullptr,            Algorithm::CN_GPU          },
+#   endif
+#   ifdef XMRIG_ALGO_CN_LITE
+    { "cryptonight-lite/0",        "cn-lite/0",        Algorithm::CN_LITE_0       },
+    { "cryptonight-lite/1",        "cn-lite/1",        Algorithm::CN_LITE_1       },
+    { "cryptonight-lite",          "cn-lite",          Algorithm::CN_LITE_1       },
+    { "cryptonight-light",         "cn-light",         Algorithm::CN_LITE_1       },
+    { "cryptonight_lite",          nullptr,            Algorithm::CN_LITE_1       },
+    { "cryptonight-aeonv7",        nullptr,            Algorithm::CN_LITE_1       },
+    { "cryptonight_lite_v7",       nullptr,            Algorithm::CN_LITE_1       },
+#   endif
+#   ifdef XMRIG_ALGO_CN_HEAVY
+    { "cryptonight-heavy/0",       "cn-heavy/0",       Algorithm::CN_HEAVY_0      },
+    { "cryptonight-heavy",         "cn-heavy",         Algorithm::CN_HEAVY_0      },
+    { "cryptonight_heavy",         nullptr,            Algorithm::CN_HEAVY_0      },
+    { "cryptonight-heavy/xhv",     "cn-heavy/xhv",     Algorithm::CN_HEAVY_XHV    },
+    { "cryptonight_haven",         nullptr,            Algorithm::CN_HEAVY_XHV    },
+    { "cryptonight-heavy/tube",    "cn-heavy/tube",    Algorithm::CN_HEAVY_TUBE   },
+    { "cryptonight-bittube2",      nullptr,            Algorithm::CN_HEAVY_TUBE   },
+#   endif
+#   ifdef XMRIG_ALGO_CN_PICO
+    { "cryptonight-pico",          "cn-pico",          Algorithm::CN_PICO         },
+    { "cryptonight-pico/trtl",     "cn-pico/trtl",     Algorithm::CN_PICO         },
+    { "cryptonight-turtle",        "cn-trtl",          Algorithm::CN_PICO         },
+    { "cryptonight-ultralite",     "cn-ultralite",     Algorithm::CN_PICO         },
+    { "cryptonight_turtle",        "cn_turtle",        Algorithm::CN_PICO         },
 #   endif
 };
 
 
-#ifdef XMRIG_PROXY_PROJECT
-static AlgoData const xmrStakAlgorithms[] = {
-    { "cryptonight-monerov7",    nullptr, xmrig::CRYPTONIGHT,       xmrig::VARIANT_1    },
-    { "cryptonight_v7",          nullptr, xmrig::CRYPTONIGHT,       xmrig::VARIANT_1    },
-    { "cryptonight-monerov8",    nullptr, xmrig::CRYPTONIGHT,       xmrig::VARIANT_2    },
-    { "cryptonight_v8",          nullptr, xmrig::CRYPTONIGHT,       xmrig::VARIANT_2    },
-    { "cryptonight_v7_stellite", nullptr, xmrig::CRYPTONIGHT,       xmrig::VARIANT_XTL  },
-    { "cryptonight_lite",        nullptr, xmrig::CRYPTONIGHT_LITE,  xmrig::VARIANT_0    },
-    { "cryptonight-aeonv7",      nullptr, xmrig::CRYPTONIGHT_LITE,  xmrig::VARIANT_1    },
-    { "cryptonight_lite_v7",     nullptr, xmrig::CRYPTONIGHT_LITE,  xmrig::VARIANT_1    },
-    { "cryptonight_heavy",       nullptr, xmrig::CRYPTONIGHT_HEAVY, xmrig::VARIANT_0    },
-    { "cryptonight_haven",       nullptr, xmrig::CRYPTONIGHT_HEAVY, xmrig::VARIANT_XHV  },
-    { "cryptonight_masari",      nullptr, xmrig::CRYPTONIGHT,       xmrig::VARIANT_MSR  },
-    { "cryptonight_masari",      nullptr, xmrig::CRYPTONIGHT,       xmrig::VARIANT_MSR  },
-    { "cryptonight-bittube2",    nullptr, xmrig::CRYPTONIGHT_HEAVY, xmrig::VARIANT_TUBE }, // bittube-miner
-    { "cryptonight_alloy",       nullptr, xmrig::CRYPTONIGHT,       xmrig::VARIANT_XAO  }, // xmr-stak-alloy
-    { "cryptonight_turtle",      nullptr, xmrig::CRYPTONIGHT_PICO,  xmrig::VARIANT_TRTL },
-    { "cryptonight_gpu",         nullptr, xmrig::CRYPTONIGHT,       xmrig::VARIANT_GPU  },
-    { "cryptonight_r",           nullptr, xmrig::CRYPTONIGHT,       xmrig::VARIANT_4  },
-};
-#endif
-
-
-static const char *variants[] = {
-    "0",
-    "1",
-    "tube",
-    "xtl",
-    "msr",
-    "xhv",
-    "xao",
-    "rto",
-    "2",
-    "half",
-    "trtl",
-    "gpu",
-    "wow",
-    "r",
-    "rwz",
-    "zls",
-    "double"
-};
-
-
-static_assert(xmrig::VARIANT_MAX == ARRAY_SIZE(variants), "variants size mismatch");
-
-
-bool xmrig::Algorithm::isValid() const
-{
-    if (m_algo == INVALID_ALGO) {
-        return false;
-    }
-
-    for (size_t i = 0; i < ARRAY_SIZE(algorithms); i++) {
-        if (algorithms[i].algo == m_algo && algorithms[i].variant == m_variant) {
-            return true;
-        }
-    }
-
-    return false;
-}
-
-
-const char *xmrig::Algorithm::variantName() const
-{
-    if (m_variant == VARIANT_AUTO) {
-        return "auto";
-    }
-
-    return variants[m_variant];
-}
-
-
-void xmrig::Algorithm::parseAlgorithm(const char *algo)
-{
-    m_algo    = INVALID_ALGO;
-    m_variant = VARIANT_AUTO;
-
-//    assert(algo != nullptr);
-    if (algo == nullptr || strlen(algo) < 1) {
-        return;
-    }
-
-    if (*algo == '!') {
-        m_flags |= Forced;
-
-        return parseAlgorithm(algo + 1);
-    }
-
-    for (size_t i = 0; i < ARRAY_SIZE(algorithms); i++) {
-        if ((strcasecmp(algo, algorithms[i].name) == 0) || (strcasecmp(algo, algorithms[i].shortName) == 0)) {
-            m_algo    = algorithms[i].algo;
-            m_variant = algorithms[i].variant;
-            break;
-        }
-    }
-
-    if (m_algo == INVALID_ALGO) {
-        assert(false);
-    }
-}
-
-
-void xmrig::Algorithm::parseVariant(const char *variant)
-{
-    m_variant = VARIANT_AUTO;
-
-    if (variant == nullptr || strlen(variant) < 1) {
-        return;
-    }
-
-    if (*variant == '!') {
-        m_flags |= Forced;
-
-        return parseVariant(variant + 1);
-    }
-
-    for (size_t i = 0; i < ARRAY_SIZE(variants); i++) {
-        if (strcasecmp(variant, variants[i]) == 0) {
-            m_variant = static_cast<Variant>(i);
-            return;
-        }
-    }
-
-    if (strcasecmp(variant, "xtlv9") == 0) {
-        m_variant = VARIANT_HALF;
-    }
-}
-
-
-void xmrig::Algorithm::parseVariant(int variant)
-{
-    assert(variant >= -1 && variant <= 2);
-
-    switch (variant) {
-    case -1:
-    case 0:
-    case 1:
-        m_variant = static_cast<Variant>(variant);
-        break;
-
-    case 2:
-        m_variant = VARIANT_2;
-        break;
-
-    default:
-        break;
-    }
-}
-
-
-void xmrig::Algorithm::setAlgo(Algo algo)
-{
-    m_algo = algo;
-
-    if (m_algo == CRYPTONIGHT_PICO && m_variant == VARIANT_AUTO) {
-        m_variant = xmrig::VARIANT_TRTL;
-    }
-}
-
-
-#ifdef XMRIG_PROXY_PROJECT
-void xmrig::Algorithm::parseXmrStakAlgorithm(const char *algo)
-{
-    m_algo    = INVALID_ALGO;
-    m_variant = VARIANT_AUTO;
-
-    assert(algo != nullptr);
-    if (algo == nullptr) {
-        return;
-    }
-
-    for (size_t i = 0; i < ARRAY_SIZE(xmrStakAlgorithms); i++) {
-        if (strcasecmp(algo, xmrStakAlgorithms[i].name) == 0) {
-            m_algo    = xmrStakAlgorithms[i].algo;
-            m_variant = xmrStakAlgorithms[i].variant;
-            break;
-        }
-    }
-
-    if (m_algo == INVALID_ALGO) {
-        assert(false);
-    }
-}
-#endif
+} /* namespace xmrig */
 
 
 const char *xmrig::Algorithm::name(bool shortName) const
 {
-    for (size_t i = 0; i < ARRAY_SIZE(algorithms); i++) {
-        if (algorithms[i].algo == m_algo && algorithms[i].variant == m_variant) {
-            return shortName ? algorithms[i].shortName : algorithms[i].name;
+    for (size_t i = 0; i < ARRAY_SIZE(algorithm_names); i++) {
+        if (algorithm_names[i].id == m_id) {
+            return shortName ? algorithm_names[i].shortName : algorithm_names[i].name;
         }
     }
 
     return "invalid";
 }
+
+
+xmrig::Algorithm::Id xmrig::Algorithm::parse(const char *name)
+{
+    if (name == nullptr || strlen(name) < 1) {
+        return INVALID;
+    }
+
+    for (size_t i = 0; i < ARRAY_SIZE(algorithm_names); i++) {
+        if ((strcasecmp(name, algorithm_names[i].name) == 0) || (algorithm_names[i].shortName != nullptr && strcasecmp(name, algorithm_names[i].shortName) == 0)) {
+            return algorithm_names[i].id;
+        }
+    }
+
+    return INVALID;
+}
diff --git a/src/crypto/common/Algorithm.h b/src/crypto/common/Algorithm.h
index 664552aa5..c70e0caa4 100644
--- a/src/crypto/common/Algorithm.h
+++ b/src/crypto/common/Algorithm.h
@@ -30,68 +30,63 @@
 #include <vector>
 
 
-#include "common/xmrig.h"
-
-
 namespace xmrig {
 
 
 class Algorithm
 {
 public:
-    enum Flags {
-        None   = 0,
-        Forced = 1
+    enum Id : int {
+        INVALID = -1,
+        CN_0,          // "cn/0"             Original CryptoNight
+        CN_1,          // "cn/1"             CryptoNight variant 1 also known as Monero7 and CryptoNightV7
+        CN_2,          // "cn/2"             CryptoNight variant 2
+        CN_R,          // "cn/r"             CryptoNightR (Monero's variant 4)
+        CN_WOW,        // "cn/wow"           CryptoNightR (Wownero)
+        CN_FAST,       // "cn/fast"          CryptoNight variant 1 with half iterations
+        CN_HALF,       // "cn/half"          CryptoNight variant 2 with half iterations (Masari/Stellite)
+        CN_XAO,        // "cn/xao"           Modified CryptoNight variant 0 (Alloy only)
+        CN_RTO,        // "cn/rto"           Modified CryptoNight variant 1 (Arto only)
+        CN_RWZ,        // "cn/rwz"           CryptoNight variant 2 with 3/4 iterations and reversed shuffle operation (Graft)
+        CN_ZLS,        // "cn/zls"           CryptoNight variant 2 with 3/4 iterations (Zelerius)
+        CN_DOUBLE,     // "cn/double"        CryptoNight variant 2 with double iterations (X-CASH)
+#       ifdef XMRIG_ALGO_CN_GPU
+        CN_GPU,        // "cn/gpu"           CryptoNight-GPU (Ryo)
+#       endif
+#       ifdef XMRIG_ALGO_CN_LITE
+        CN_LITE_0,     // "cn-lite/0"        CryptoNight-Lite (1 MB) variant 0
+        CN_LITE_1,     // "cn-lite/1"        CryptoNight-Lite (1 MB) variant 1
+#       endif
+#       ifdef XMRIG_ALGO_CN_HEAVY
+        CN_HEAVY_0,    // "cn-heavy/0"       CryptoNight-Heavy (4 MB)
+        CN_HEAVY_TUBE, // "cn-heavy/tube"    Modified CryptoNight-Heavy (TUBE only)
+        CN_HEAVY_XHV,  // "cn-heavy/xhv"     Modified CryptoNight-Heavy (Haven Protocol only)
+#       endif
+#       ifdef XMRIG_ALGO_CN_PICO
+        CN_PICO,       // "cn-pico"          CryptoNight Turtle (TRTL)
+#       endif
+        MAX
     };
 
-    inline Algorithm() :
-        m_algo(INVALID_ALGO),
-        m_flags(0),
-        m_variant(VARIANT_AUTO)
-    {}
+    inline Algorithm()                                     {}
+    inline Algorithm(const char *algo) : m_id(parse(algo)) {}
+    inline Algorithm(Id id) : m_id(id)                     {}
 
-    inline Algorithm(Algo algo, Variant variant) :
-        m_flags(0),
-        m_variant(variant)
-    {
-        setAlgo(algo);
-    }
-
-    inline Algorithm(const char *algo) :
-        m_flags(0)
-    {
-        parseAlgorithm(algo);
-    }
-
-    inline Algo algo() const                          { return m_algo; }
-    inline bool isEqual(const Algorithm &other) const { return m_algo == other.m_algo && m_variant == other.m_variant; }
-    inline bool isForced() const                      { return m_flags & Forced; }
+    inline bool isEqual(const Algorithm &other) const { return m_id == other.m_id; }
     inline const char *name() const                   { return name(false); }
     inline const char *shortName() const              { return name(true); }
-    inline int flags() const                          { return m_flags; }
-    inline Variant variant() const                    { return m_variant; }
-    inline void setVariant(Variant variant)           { m_variant = variant; }
+    inline Id id() const                              { return m_id; }
+    inline bool isValid() const                       { return m_id != INVALID; }
 
     inline bool operator!=(const Algorithm &other) const  { return !isEqual(other); }
     inline bool operator==(const Algorithm &other) const  { return isEqual(other); }
 
-    bool isValid() const;
-    const char *variantName() const;
-    void parseAlgorithm(const char *algo);
-    void parseVariant(const char *variant);
-    void parseVariant(int variant);
-    void setAlgo(Algo algo);
-
-#   ifdef XMRIG_PROXY_PROJECT
-    void parseXmrStakAlgorithm(const char *algo);
-#   endif
+    static Id parse(const char *name);
 
 private:
     const char *name(bool shortName) const;
 
-    Algo m_algo;
-    int m_flags;
-    Variant m_variant;
+    Id m_id = INVALID;
 };
 
 
@@ -100,4 +95,5 @@ typedef std::vector<xmrig::Algorithm> Algorithms;
 
 } /* namespace xmrig */
 
-#endif /* __ALGORITHM_H__ */
+
+#endif /* XMRIG_ALGORITHM_H */
diff --git a/src/net/Network.cpp b/src/net/Network.cpp
index 1ab422368..16669f52e 100644
--- a/src/net/Network.cpp
+++ b/src/net/Network.cpp
@@ -231,8 +231,7 @@ void xmrig::Network::getConnection(rapidjson::Value &reply, rapidjson::Document
     using namespace rapidjson;
     auto &allocator = doc.GetAllocator();
 
-    const Algorithm &algo = m_strategy->client()->job().algorithm();
-    reply.AddMember("algo", StringRef((algo.isValid() ? algo : m_controller->config()->algorithm()).shortName()), allocator);
+    reply.AddMember("algo", StringRef(m_strategy->client()->job().algorithm().shortName()), allocator);
 
     Value connection(kObjectType);
     connection.AddMember("pool",            StringRef(m_state.pool), allocator);
diff --git a/src/net/strategies/DonateStrategy.cpp b/src/net/strategies/DonateStrategy.cpp
index fb958a4c5..3d9130876 100644
--- a/src/net/strategies/DonateStrategy.cpp
+++ b/src/net/strategies/DonateStrategy.cpp
@@ -79,9 +79,9 @@ xmrig::DonateStrategy::DonateStrategy(Controller *controller, IStrategyListener
 #   endif
     m_pools.push_back(Pool(kDonateHost, 3333, m_userId, nullptr, 0, true));
 
-    for (Pool &pool : m_pools) {
-        pool.adjust(Algorithm(controller->config()->algorithm().algo(), VARIANT_AUTO));
-    }
+//    for (Pool &pool : m_pools) {
+//        pool.adjust(Algorithm()); // FIXME
+//    }
 
     if (m_pools.size() > 1) {
         m_strategy = new FailoverStrategy(m_pools, 1, 2, this, true);
diff --git a/src/workers/MultiWorker.cpp b/src/workers/MultiWorker.cpp
index e4a5fb0c7..30c430001 100644
--- a/src/workers/MultiWorker.cpp
+++ b/src/workers/MultiWorker.cpp
@@ -126,7 +126,8 @@ void MultiWorker<N>::start()
                 storeStats();
             }
 
-            m_thread->fn(m_state.job.algorithm().variant())(m_state.blob, m_state.job.size(), m_hash, m_ctx, m_state.job.height());
+            // FIXME
+//            m_thread->fn(m_state.job.algorithm().variant())(m_state.blob, m_state.job.size(), m_hash, m_ctx, m_state.job.height());
 
             for (size_t i = 0; i < N; ++i) {
                 if (*reinterpret_cast<uint64_t*>(m_hash + (i * 32) + 24) < m_state.job.target()) {
diff --git a/src/workers/Workers.cpp b/src/workers/Workers.cpp
index b95d8b852..62cbd1cfa 100644
--- a/src/workers/Workers.cpp
+++ b/src/workers/Workers.cpp
@@ -176,7 +176,7 @@ void Workers::start(xmrig::Controller *controller)
     m_controller = controller;
 
     const std::vector<xmrig::IThread *> &threads = controller->config()->threads();
-    m_status.algo    = controller->config()->algorithm().algo();
+//    m_status.algo    = controller->config()->algorithm().algo(); // FIXME
     m_status.threads = threads.size();
 
     for (const xmrig::IThread *thread : threads) {