diff --git a/src/avalanche/peermanager.cpp b/src/avalanche/peermanager.cpp
--- a/src/avalanche/peermanager.cpp
+++ b/src/avalanche/peermanager.cpp
@@ -165,7 +165,8 @@
 
 static bool isOrphanState(const ProofValidationState &state) {
     return state.GetResult() == ProofValidationResult::MISSING_UTXO ||
-           state.GetResult() == ProofValidationResult::HEIGHT_MISMATCH;
+           state.GetResult() == ProofValidationResult::HEIGHT_MISMATCH ||
+           state.GetResult() == ProofValidationResult::IMMATURE_UTXO;
 }
 
 bool PeerManager::updateNextPossibleConflictTime(
diff --git a/src/avalanche/proof.h b/src/avalanche/proof.h
--- a/src/avalanche/proof.h
+++ b/src/avalanche/proof.h
@@ -32,6 +32,13 @@
  */
 static constexpr bool AVALANCHE_DEFAULT_LEGACY_PROOF = true;
 
+/**
+ * Minimum number of confirmations before a stake utxo is mature enough to be
+ * included into a proof.
+ * FIXME: Set to sane default after the tests have been updated.
+ */
+static constexpr int AVALANCHE_DEFAULT_STAKE_UTXO_CONFIRMATIONS = 0;
+
 namespace avalanche {
 
 /** Minimum amount per utxo */
diff --git a/src/avalanche/proof.cpp b/src/avalanche/proof.cpp
--- a/src/avalanche/proof.cpp
+++ b/src/avalanche/proof.cpp
@@ -13,6 +13,7 @@
 #include <util/strencodings.h>
 #include <util/system.h>
 #include <util/translation.h>
+#include <validation.h> // For g_chainman
 
 #include <tinyformat.h>
 
@@ -185,10 +186,24 @@
         return false;
     }
 
+    const int64_t activeHeight =
+        WITH_LOCK(cs_main, return g_chainman.ActiveHeight());
+    const int64_t stakeUtxoMinConfirmations =
+        gArgs.GetArg("-avaproofstakeutxoconfirmations",
+                     AVALANCHE_DEFAULT_STAKE_UTXO_CONFIRMATIONS);
+
     for (const SignedStake &ss : stakes) {
         const Stake &s = ss.getStake();
         const COutPoint &utxo = s.getUTXO();
 
+        if ((s.getHeight() + stakeUtxoMinConfirmations) > activeHeight) {
+            return state.Invalid(
+                ProofValidationResult::IMMATURE_UTXO, "immature-utxo",
+                strprintf("TxId: %s, block height: %d, chaintip height: %d",
+                          s.getUTXO().GetTxId().ToString(), s.getHeight(),
+                          activeHeight));
+        }
+
         Coin coin;
         if (!view.GetCoin(utxo, coin)) {
             // The coins are not in the UTXO set.
diff --git a/src/avalanche/test/init_tests.cpp b/src/avalanche/test/init_tests.cpp
--- a/src/avalanche/test/init_tests.cpp
+++ b/src/avalanche/test/init_tests.cpp
@@ -39,6 +39,8 @@
 
         BOOST_CHECK_EQUAL(args.GetBoolArg("-enableavalanche", false), true);
         BOOST_CHECK_EQUAL(args.GetBoolArg("-legacyavaproof", true), false);
+        BOOST_CHECK_EQUAL(args.GetArg("-avaproofstakeutxoconfirmations", 42),
+                          2016);
         BOOST_CHECK_EQUAL(
             args.GetBoolArg("-enableavalanchepeerdiscovery", false), true);
         BOOST_CHECK_EQUAL(
@@ -60,6 +62,8 @@
         BOOST_CHECK_EQUAL(args.GetBoolArg("-enableavalanche", true), false);
         BOOST_CHECK_EQUAL(args.GetBoolArg("-legacyavaproof", false),
                           AVALANCHE_DEFAULT_LEGACY_PROOF);
+        BOOST_CHECK_EQUAL(args.GetArg("-avaproofstakeutxoconfirmations", 42),
+                          AVALANCHE_DEFAULT_STAKE_UTXO_CONFIRMATIONS);
         BOOST_CHECK_EQUAL(
             args.GetBoolArg("-enableavalanchepeerdiscovery", true), false);
         BOOST_CHECK_EQUAL(
@@ -79,6 +83,7 @@
         ArgsManager args;
         args.ForceSetArg("-avalanche", "1");
         args.ForceSetArg("-legacyavaproof", "1");
+        args.ForceSetArg("-avaproofstakeutxoconfirmations", "500");
         args.ForceSetArg("-enableavalancheproofreplacement", "0");
         args.ForceSetArg("-automaticunparking", "1");
         args.ForceSetArg("-avaminquorumstake", FormatMoney(123 * COIN));
@@ -87,6 +92,8 @@
 
         BOOST_CHECK_EQUAL(args.GetBoolArg("-enableavalanche", false), true);
         BOOST_CHECK_EQUAL(args.GetBoolArg("-legacyavaproof", false), true);
+        BOOST_CHECK_EQUAL(args.GetArg("-avaproofstakeutxoconfirmations", 42),
+                          500);
         BOOST_CHECK_EQUAL(
             args.GetBoolArg("-enableavalanchepeerdiscovery", false), true);
         BOOST_CHECK_EQUAL(
diff --git a/src/avalanche/test/peermanager_tests.cpp b/src/avalanche/test/peermanager_tests.cpp
--- a/src/avalanche/test/peermanager_tests.cpp
+++ b/src/avalanche/test/peermanager_tests.cpp
@@ -117,7 +117,7 @@
 } // namespace avalanche
 
 namespace {
-struct NoCoolDownFixture : public TestingSetup {
+struct NoCoolDownFixture : public TestChain100Setup {
     NoCoolDownFixture() {
         gArgs.ForceSetArg("-avalancheconflictingproofcooldown", "0");
     }
@@ -127,7 +127,7 @@
 };
 } // namespace
 
-BOOST_FIXTURE_TEST_SUITE(peermanager_tests, TestingSetup)
+BOOST_FIXTURE_TEST_SUITE(peermanager_tests, TestChain100Setup)
 
 BOOST_AUTO_TEST_CASE(select_peer_linear) {
     // No peers.
@@ -694,6 +694,7 @@
 }
 
 BOOST_AUTO_TEST_CASE(orphan_proofs) {
+    gArgs.ForceSetArg("-avaproofstakeutxoconfirmations", "1");
     avalanche::PeerManager pm;
 
     auto key = CKey::MakeCompressedKey();
@@ -701,10 +702,12 @@
     COutPoint outpoint1 = COutPoint(TxId(GetRandHash()), 0);
     COutPoint outpoint2 = COutPoint(TxId(GetRandHash()), 0);
     COutPoint outpoint3 = COutPoint(TxId(GetRandHash()), 0);
+    COutPoint outpoint4 = COutPoint(TxId(GetRandHash()), 0);
 
     const Amount v = 5 * COIN;
-    const int height = 1234;
-    const int wrongHeight = 12345;
+    const int height = 98;
+    const int wrongHeight = 99;
+    const int immatureHeight = 100;
 
     const auto makeProof = [&](const COutPoint &outpoint, const int h) {
         return buildProofWithOutpoints(key, {outpoint}, v, key, 0, h);
@@ -713,10 +716,12 @@
     auto proof1 = makeProof(outpoint1, height);
     auto proof2 = makeProof(outpoint2, height);
     auto proof3 = makeProof(outpoint3, wrongHeight);
+    auto proof4 = makeProof(outpoint4, immatureHeight);
 
-    // Add outpoints 1 and 3, not 2
+    // Add outpoints, except for proof 2
     addCoin(outpoint1, key, v, height);
     addCoin(outpoint3, key, v, height);
+    addCoin(outpoint4, key, v, immatureHeight);
 
     // Add the proofs
     BOOST_CHECK(pm.registerProof(proof1));
@@ -729,6 +734,7 @@
 
     registerOrphan(proof2);
     registerOrphan(proof3);
+    registerOrphan(proof4);
 
     auto checkOrphan = [&](const ProofRef &proof, bool expectedOrphan) {
         const ProofId &proofid = proof->getId();
@@ -752,6 +758,8 @@
     checkOrphan(proof2, true);
     // HEIGHT_MISMATCH
     checkOrphan(proof3, true);
+    // IMMATURE_UTXO
+    checkOrphan(proof4, true);
 
     // Add outpoint2, proof2 is no longer considered orphan
     addCoin(outpoint2, key, v, height);
@@ -763,6 +771,11 @@
     checkOrphan(proof1, false);
     checkOrphan(proof3, true);
 
+    // Mine a block to increase the chain height for proof4 verification
+    mineBlocks(1);
+    pm.updatedBlockTip();
+    checkOrphan(proof4, false);
+
     // Spend outpoint1, proof1 becomes orphan
     {
         LOCK(cs_main);
@@ -795,8 +808,6 @@
     // Track expected orphans so we can test them later
     std::vector<ProofRef> orphans;
     orphans.push_back(proof1);
-    orphans.push_back(proof2);
-    orphans.push_back(proof3);
 
     // Fill up orphan pool to test the size limit
     for (uint32_t i = 1; i < AVALANCHE_MAX_ORPHAN_PROOFS; i++) {
@@ -834,6 +845,11 @@
         CCoinsViewCache &coins = ::ChainstateActive().CoinsTip();
         coins.SpendCoin(outpoint2);
         coins.SpendCoin(outpoint3);
+        coins.SpendCoin(outpoint4);
+
+        orphans.push_back(proof2);
+        orphans.push_back(proof3);
+        orphans.push_back(proof4);
     }
 
     pm.updatedBlockTip();
@@ -865,6 +881,8 @@
         }
     }
     BOOST_CHECK_EQUAL(numOrphans, AVALANCHE_MAX_ORPHAN_PROOFS);
+
+    gArgs.ClearForcedArg("-avaproofstakeutxoconfirmations");
 }
 
 BOOST_AUTO_TEST_CASE(dangling_node) {
diff --git a/src/avalanche/test/proof_tests.cpp b/src/avalanche/test/proof_tests.cpp
--- a/src/avalanche/test/proof_tests.cpp
+++ b/src/avalanche/test/proof_tests.cpp
@@ -11,6 +11,7 @@
 #include <script/standard.h>
 #include <util/strencodings.h>
 #include <util/translation.h>
+#include <validation.h>
 
 #include <test/util/setup_common.h>
 
@@ -18,7 +19,7 @@
 
 using namespace avalanche;
 
-BOOST_FIXTURE_TEST_SUITE(proof_tests, TestingSetup)
+BOOST_FIXTURE_TEST_SUITE(proof_tests, TestChain100Setup)
 
 BOOST_AUTO_TEST_CASE(proof_random) {
     for (int i = 0; i < 1000; i++) {
@@ -1024,6 +1025,38 @@
         BOOST_CHECK(state.GetResult() ==
                     ProofValidationResult::WRONG_STAKE_ORDERING);
     }
+
+    // Immature stake
+    {
+        uint32_t chaintipHeight = ::ChainActive().Height();
+
+        // tuple<stake utxo confs, avaproofstakeutxoconfirmations, result>
+        std::vector<std::tuple<uint32_t, std::string, ProofValidationResult>>
+            testCases = {
+                // Require less or equal the number of confirmations the stake
+                // has
+                {chaintipHeight, "0", ProofValidationResult::NONE},
+                {50, "0", ProofValidationResult::NONE},
+                {50, "49", ProofValidationResult::NONE},
+                {50, "50", ProofValidationResult::NONE},
+                // Require more than the number of confirmations the stake has
+                {chaintipHeight, "1", ProofValidationResult::IMMATURE_UTXO},
+                {50, "51", ProofValidationResult::IMMATURE_UTXO},
+                {50, "100", ProofValidationResult::IMMATURE_UTXO},
+            };
+
+        for (auto it = testCases.begin(); it != testCases.end(); ++it) {
+            const uint32_t stakeConfs = std::get<0>(*it);
+            COutPoint outpoint(TxId(InsecureRand256()), InsecureRand32());
+            CTxOut output(value, GetScriptForRawPubKey(pubkey));
+            coins.AddCoin(outpoint, Coin(output, stakeConfs, false), false);
+
+            gArgs.ForceSetArg("-avaproofstakeutxoconfirmations",
+                              std::get<1>(*it));
+            runCheck(std::get<2>(*it), outpoint, value, stakeConfs, false, key);
+        }
+        gArgs.ClearForcedArg("-avaproofstakeutxoconfirmations");
+    }
 }
 
 BOOST_AUTO_TEST_CASE(deterministic_proofid) {
diff --git a/src/avalanche/test/proofpool_tests.cpp b/src/avalanche/test/proofpool_tests.cpp
--- a/src/avalanche/test/proofpool_tests.cpp
+++ b/src/avalanche/test/proofpool_tests.cpp
@@ -18,7 +18,7 @@
 
 using namespace avalanche;
 
-BOOST_FIXTURE_TEST_SUITE(proofpool_tests, TestingSetup)
+BOOST_FIXTURE_TEST_SUITE(proofpool_tests, TestChain100Setup)
 
 BOOST_AUTO_TEST_CASE(add_remove_proof_no_conflict) {
     ProofPool testPool;
diff --git a/src/avalanche/test/util.cpp b/src/avalanche/test/util.cpp
--- a/src/avalanche/test/util.cpp
+++ b/src/avalanche/test/util.cpp
@@ -22,7 +22,7 @@
 
     const COutPoint o(TxId(GetRandHash()), 0);
     const Amount v = (int64_t(score) * COIN) / 100;
-    const int height = 1234;
+    const int height = 100;
     const bool is_coinbase = false;
 
     {
diff --git a/src/avalanche/validation.h b/src/avalanche/validation.h
--- a/src/avalanche/validation.h
+++ b/src/avalanche/validation.h
@@ -28,6 +28,7 @@
     NON_STANDARD_DESTINATION,
     DESTINATION_NOT_SUPPORTED,
     DESTINATION_MISMATCH,
+    IMMATURE_UTXO,
 };
 
 class ProofValidationState : public ValidationState<ProofValidationResult> {};
diff --git a/src/init.cpp b/src/init.cpp
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -1392,6 +1392,13 @@
         strprintf("Use the legacy avalanche proof format (default: %u)",
                   AVALANCHE_DEFAULT_LEGACY_PROOF),
         ArgsManager::ALLOW_BOOL, OptionsCategory::AVALANCHE);
+    argsman.AddArg(
+        "-avaproofstakeutxoconfirmations",
+        strprintf(
+            "Minimum number of confirmations before a stake utxo is mature"
+            " enough to be included into a proof (default: %s)",
+            AVALANCHE_DEFAULT_STAKE_UTXO_CONFIRMATIONS),
+        ArgsManager::ALLOW_INT, OptionsCategory::AVALANCHE);
     argsman.AddArg("-avamasterkey",
                    "Master key associated with the proof. If a proof is "
                    "required, this is mandatory.",
@@ -1670,6 +1677,10 @@
         args.SoftSetBoolArg("-legacyavaproof",
                             fAvalanche ? false
                                        : AVALANCHE_DEFAULT_LEGACY_PROOF);
+        args.SoftSetArg(
+            "-avaproofstakeutxoconfirmations",
+            fAvalanche ? "2016"
+                       : ToString(AVALANCHE_DEFAULT_STAKE_UTXO_CONFIRMATIONS));
         args.SoftSetBoolArg("-enableavalanchepeerdiscovery", fAvalanche);
         args.SoftSetBoolArg("-enableavalancheproofreplacement", fAvalanche);
         args.SoftSetBoolArg("-automaticunparking", !fAvalanche);
@@ -2136,6 +2147,15 @@
             "No proxy server specified. Use -proxy=<ip> or -proxy=<ip:port>."));
     }
 
+    // Avalanche parameters
+    const int64_t stakeUtxoMinConfirmations =
+        gArgs.GetArg("-avaproofstakeutxoconfirmations",
+                     AVALANCHE_DEFAULT_STAKE_UTXO_CONFIRMATIONS);
+    if (!chainparams.IsTestChain() && stakeUtxoMinConfirmations != 2016) {
+        return InitError(_("Avalanche stake UTXO minimum confirmations can "
+                           "only be set on test chains."));
+    }
+
     return true;
 }