diff --git a/src/avalanche/test/processor_tests.cpp b/src/avalanche/test/processor_tests.cpp
--- a/src/avalanche/test/processor_tests.cpp
+++ b/src/avalanche/test/processor_tests.cpp
@@ -1299,7 +1299,8 @@
 
         // Min stake is out of range
         {"-1", "0", false},
-        {"21000000001", "0", false},
+        {"-0.01", "0", false},
+        {"21000000000000.01", "0", false},
 
         // Min connected ratio is out of range
         {"0", "-1", false},
@@ -1307,10 +1308,12 @@
 
         // Both parameters are valid
         {"0", "0", true},
+        {"0.00", "0", true},
+        {"0.01", "0", true},
         {"1", "0.1", true},
         {"10", "0.5", true},
         {"10", "1", true},
-        {ToString(MAX_MONEY / COIN), "0", true},
+        {"21000000000000.00", "0", true},
     };
 
     // For each case set the parameters and check that making the processor
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -1437,6 +1437,9 @@
     BOOST_CHECK(ParseMoney("1234567.89", ret));
     BOOST_CHECK_EQUAL(ret, 123456789 * SATOSHI);
 
+    BOOST_CHECK(ParseMoney("21000000000000.00", ret));
+    BOOST_CHECK_EQUAL(ret, MAX_MONEY);
+
     const auto XEC = Currency::get().baseunit;
     BOOST_CHECK(ParseMoney("100000000.00", ret));
     BOOST_CHECK_EQUAL(ret, 100000000 * XEC);
@@ -1474,14 +1477,14 @@
     BOOST_CHECK_EQUAL(ret, XEC / 100);
     BOOST_CHECK(ParseMoney(" 0.01", ret));
     BOOST_CHECK_EQUAL(ret, XEC / 100);
+
+    // Parsing amount that can not be represented in ret should fail
     BOOST_CHECK(!ParseMoney("0.001", ret));
     BOOST_CHECK(!ParseMoney("0.0001", ret));
     BOOST_CHECK(!ParseMoney("0.00001", ret));
     BOOST_CHECK(!ParseMoney("0.000001", ret));
     BOOST_CHECK(!ParseMoney("0.0000001", ret));
     BOOST_CHECK(!ParseMoney("0.00000001", ret));
-
-    // Parsing amount that can not be represented in ret should fail
     BOOST_CHECK(!ParseMoney("0.000000001", ret));
 
     // Parsing empty string should fail
@@ -1495,8 +1498,12 @@
     BOOST_CHECK(!ParseMoney(" 1.2 3 ", ret));
     BOOST_CHECK(!ParseMoney(" 1 2.3 ", ret));
 
+    // Max possible value with the max number of digits
+    BOOST_CHECK(ParseMoney("9999999999999999.99", ret));
+    BOOST_CHECK_EQUAL(ret, 999999999999999999 * SATOSHI);
     // Attempted 63 bit overflow should fail
-    BOOST_CHECK(!ParseMoney("92233720368.54775808", ret));
+    BOOST_CHECK(!ParseMoney("10000000000000000.00", ret));
+    BOOST_CHECK(!ParseMoney("92233720368547758.08", ret));
 
     // Parsing negative amounts must fail
     BOOST_CHECK(!ParseMoney("-1", ret));
diff --git a/src/util/moneystr.cpp b/src/util/moneystr.cpp
--- a/src/util/moneystr.cpp
+++ b/src/util/moneystr.cpp
@@ -42,7 +42,7 @@
         return false;
     }
 
-    const auto currency = Currency::get();
+    const auto &currency = Currency::get();
     std::string strWhole;
     Amount nUnits = Amount::zero();
     const char *p = str.c_str();
@@ -67,8 +67,14 @@
     if (*p) {
         return false;
     }
+
+    // Make sure the following overflow check is meaningful. It's fine to assert
+    // because it's on no critical path, and it's very unlikely to support a 19
+    // decimal (or more) currency anyway.
+    assert(currency.decimals <= 18);
+
     // guard against 63 bit overflow
-    if (strWhole.size() > 10) {
+    if (strWhole.size() > (size_t(18) - currency.decimals)) {
         return false;
     }
     if (nUnits < Amount::zero() || nUnits > currency.baseunit) {