diff --git a/rskj-core/src/main/java/co/rsk/RskContext.java b/rskj-core/src/main/java/co/rsk/RskContext.java
index 8caf3b324f4..2a1fdaa848f 100644
--- a/rskj-core/src/main/java/co/rsk/RskContext.java
+++ b/rskj-core/src/main/java/co/rsk/RskContext.java
@@ -105,7 +105,7 @@
 import org.ethereum.facade.Ethereum;
 import org.ethereum.facade.EthereumImpl;
 import org.ethereum.listener.CompositeEthereumListener;
-import org.ethereum.listener.GasCalculator;
+import org.ethereum.listener.GasPriceCalculator;
 import org.ethereum.listener.GasPriceTracker;
 import org.ethereum.net.EthereumChannelInitializerFactory;
 import org.ethereum.net.NodeManager;
@@ -556,7 +556,7 @@ public synchronized Ethereum getRsk() {
     public GasPriceTracker getGasPriceTracker() {
         checkIfNotClosed();
         if (this.gasPriceTracker == null) {
-            GasCalculator.GasCalculatorType calculatorType = getRskSystemProperties().getGasCalculatorType();
+            GasPriceCalculator.GasCalculatorType calculatorType = getRskSystemProperties().getGasCalculatorType();
             this.gasPriceTracker = GasPriceTracker.create(getBlockStore(), calculatorType);
         }
         return this.gasPriceTracker;
diff --git a/rskj-core/src/main/java/co/rsk/config/RskSystemProperties.java b/rskj-core/src/main/java/co/rsk/config/RskSystemProperties.java
index 05cac5fa073..7c37a790cd4 100644
--- a/rskj-core/src/main/java/co/rsk/config/RskSystemProperties.java
+++ b/rskj-core/src/main/java/co/rsk/config/RskSystemProperties.java
@@ -29,7 +29,7 @@
 import org.ethereum.core.Account;
 import org.ethereum.crypto.ECKey;
 import org.ethereum.crypto.HashUtil;
-import org.ethereum.listener.GasCalculator;
+import org.ethereum.listener.GasPriceCalculator;
 
 import javax.annotation.Nullable;
 import java.nio.charset.StandardCharsets;
@@ -485,12 +485,12 @@ public double getTopBest() {
         return value;
     }
 
-    public GasCalculator.GasCalculatorType getGasCalculatorType() {
+    public GasPriceCalculator.GasCalculatorType getGasCalculatorType() {
         String value = configFromFiles.getString(MINER_GAS_PRICE_CALCULATOR_TYPE);
         if (value == null || value.isEmpty()) {
-            return GasCalculator.GasCalculatorType.LEGACY;
+            return GasPriceCalculator.GasCalculatorType.PLAIN_PERCENTILE;
         }
-        GasCalculator.GasCalculatorType gasCalculatorType = GasCalculator.GasCalculatorType.fromString(value);
+        GasPriceCalculator.GasCalculatorType gasCalculatorType = GasPriceCalculator.GasCalculatorType.fromString(value);
         if(gasCalculatorType == null) {
             throw new RskConfigurationException("Invalid gasPriceCalculatorType: " + value);
         }
diff --git a/rskj-core/src/main/java/org/ethereum/listener/GasCalculator.java b/rskj-core/src/main/java/org/ethereum/listener/GasPriceCalculator.java
similarity index 81%
rename from rskj-core/src/main/java/org/ethereum/listener/GasCalculator.java
rename to rskj-core/src/main/java/org/ethereum/listener/GasPriceCalculator.java
index c69502ba42e..a8be9510a34 100644
--- a/rskj-core/src/main/java/org/ethereum/listener/GasCalculator.java
+++ b/rskj-core/src/main/java/org/ethereum/listener/GasPriceCalculator.java
@@ -24,20 +24,20 @@
 import java.util.List;
 import java.util.Optional;
 
-public interface GasCalculator {
+public interface GasPriceCalculator {
     public enum GasCalculatorType {
-        LEGACY,
-        WEIGHTED;
+        PLAIN_PERCENTILE,
+        WEIGHTED_PERCENTILE;
 
         public static GasCalculatorType fromString(String type) {
             if (type == null) {
                 return null;
             }
             switch (type.toLowerCase()) {
-                case "weighted":
-                    return WEIGHTED;
-                case "legacy":
-                    return LEGACY;
+                case "weighted_percentile":
+                    return WEIGHTED_PERCENTILE;
+                case "plain_percentile":
+                    return PLAIN_PERCENTILE;
                 default:
                     return null;
             }
@@ -46,4 +46,6 @@ public static GasCalculatorType fromString(String type) {
 
     Optional<Coin> getGasPrice();
     void onBlock(Block block, List<TransactionReceipt> receipts);
+
+    GasCalculatorType getType();
 }
diff --git a/rskj-core/src/main/java/org/ethereum/listener/GasPriceTracker.java b/rskj-core/src/main/java/org/ethereum/listener/GasPriceTracker.java
index e0053c7935a..e4929c2124f 100644
--- a/rskj-core/src/main/java/org/ethereum/listener/GasPriceTracker.java
+++ b/rskj-core/src/main/java/org/ethereum/listener/GasPriceTracker.java
@@ -61,21 +61,21 @@ public class GasPriceTracker extends EthereumListenerAdapter {
     private Coin defaultPrice = Coin.valueOf(20_000_000_000L);
     private int blockIdx = 0;
 
-    private final GasCalculator gasCalculator;
+    private final GasPriceCalculator gasPriceCalculator;
 
-    private GasPriceTracker(BlockStore blockStore, GasCalculator gasCalculator) {
+    private GasPriceTracker(BlockStore blockStore, GasPriceCalculator gasPriceCalculator) {
         this.blockStore = blockStore;
-        this.gasCalculator = gasCalculator;
+        this.gasPriceCalculator = gasPriceCalculator;
     }
 
-    public static GasPriceTracker create(BlockStore blockStore, GasCalculator.GasCalculatorType gasCalculatorType) {
-        GasCalculator gasCal;
+    public static GasPriceTracker create(BlockStore blockStore, GasPriceCalculator.GasCalculatorType gasCalculatorType) {
+        GasPriceCalculator gasCal;
         switch (gasCalculatorType) {
-            case WEIGHTED:
-                gasCal = new GasWeightedCalc();
+            case WEIGHTED_PERCENTILE:
+                gasCal = new WeightedPercentileGasPriceCalculator();
                 break;
-            case LEGACY:
-                gasCal = new LegacyGasCalculator();
+            case PLAIN_PERCENTILE:
+                gasCal = new PercentileGasPriceCalculator();
                 break;
             default:
                 throw new IllegalArgumentException("Unknown gas calculator type: " + gasCalculatorType);
@@ -87,14 +87,12 @@ public static GasPriceTracker create(BlockStore blockStore, GasCalculator.GasCal
     }
 
     /**
-     * @deprecated Use {@link #create(BlockStore, GasCalculator.GasCalculatorType)} instead.
+     * @deprecated Use {@link #create(BlockStore, GasPriceCalculator.GasCalculatorType)} instead.
      */
     @Deprecated
     public static GasPriceTracker create(BlockStore blockStore) {
         //Will be using the legacy gas calculator as default option
-        GasPriceTracker gasPriceTracker = new GasPriceTracker(blockStore, new LegacyGasCalculator());
-        gasPriceTracker.initializeWindowsFromDB();
-        return gasPriceTracker;
+        return GasPriceTracker.create(blockStore, GasPriceCalculator.GasCalculatorType.PLAIN_PERCENTILE);
     }
 
     @Override
@@ -110,17 +108,17 @@ public synchronized void onBlock(Block block, List<TransactionReceipt> receipts)
 
         trackBlockCompleteness(block);
 
-        gasCalculator.onBlock(block, receipts);
+        gasPriceCalculator.onBlock(block, receipts);
         logger.trace("End onBlock");
     }
 
     public synchronized Coin getGasPrice() {
-        Optional<Coin> gasPriceResult = gasCalculator.getGasPrice();
+        Optional<Coin> gasPriceResult = gasPriceCalculator.getGasPrice();
         if(!gasPriceResult.isPresent()) {
             return defaultPrice;
         }
 
-        logger.debug("Gas provided by GasWindowCalc: {}", gasCalculator.getGasPrice());
+        logger.debug("Gas provided by GasWindowCalc: {}", gasPriceCalculator.getGasPrice());
 
         Coin bestBlockPrice = bestBlockPriceRef.get();
         if (bestBlockPrice == null) {
@@ -191,4 +189,8 @@ private void trackBlockCompleteness(Block block) {
         blockWindow[blockIdx++] = completeness;
     }
 
+    public GasPriceCalculator.GasCalculatorType getGasCalculatorType() {
+        return gasPriceCalculator.getType();
+    }
+
 }
diff --git a/rskj-core/src/main/java/org/ethereum/listener/LegacyGasCalculator.java b/rskj-core/src/main/java/org/ethereum/listener/PercentileGasPriceCalculator.java
similarity index 92%
rename from rskj-core/src/main/java/org/ethereum/listener/LegacyGasCalculator.java
rename to rskj-core/src/main/java/org/ethereum/listener/PercentileGasPriceCalculator.java
index 766accedb1d..58818f88a51 100644
--- a/rskj-core/src/main/java/org/ethereum/listener/LegacyGasCalculator.java
+++ b/rskj-core/src/main/java/org/ethereum/listener/PercentileGasPriceCalculator.java
@@ -28,7 +28,7 @@
 import java.util.List;
 import java.util.Optional;
 
-public class LegacyGasCalculator implements GasCalculator {
+public class PercentileGasPriceCalculator implements GasPriceCalculator {
     private static final int TX_WINDOW_SIZE = 512;
 
     private final Coin[] txWindow = new Coin[TX_WINDOW_SIZE];
@@ -53,6 +53,11 @@ public void onBlock(Block block, List<TransactionReceipt> receipts) {
        onBlock(block.getTransactionsList());
     }
 
+    @Override
+    public GasCalculatorType getType() {
+        return GasCalculatorType.PLAIN_PERCENTILE;
+    }
+
     private void onBlock(List<Transaction> transactionList) {
         for (Transaction tx : transactionList) {
             if (!(tx instanceof RemascTransaction)) {
diff --git a/rskj-core/src/main/java/org/ethereum/listener/WeightedPercentileCalc.java b/rskj-core/src/main/java/org/ethereum/listener/WeightedPercentileCalc.java
new file mode 100644
index 00000000000..775da8ed65e
--- /dev/null
+++ b/rskj-core/src/main/java/org/ethereum/listener/WeightedPercentileCalc.java
@@ -0,0 +1,50 @@
+/*
+ * This file is part of RskJ
+ * Copyright (C) 2024 RSK Labs Ltd.
+ * (derived from ethereumJ library, Copyright (c) 2016 <ether.camp>)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.ethereum.listener;
+
+import co.rsk.core.Coin;
+
+import java.util.Collections;
+import java.util.List;
+
+public class WeightedPercentileCalc {
+
+    public Coin calculateWeightedPercentile(float percentile, List<WeightedPercentileGasPriceCalculator.GasEntry> gasEntries) {
+        if (gasEntries == null || gasEntries.isEmpty()) {
+            return null;
+        }
+
+        Collections.sort(gasEntries);
+
+        double totalWeight = gasEntries.stream().mapToLong(WeightedPercentileGasPriceCalculator.GasEntry::getGasUsed).sum();
+
+        double targetWeight = percentile / 100 * totalWeight;
+
+
+        double cumulativeWeight = 0;
+        for (WeightedPercentileGasPriceCalculator.GasEntry pair : gasEntries) {
+            cumulativeWeight += pair.getGasUsed();
+            if (cumulativeWeight >= targetWeight) {
+                return pair.getGasPrice();
+            }
+        }
+
+        return null;
+    }
+}
diff --git a/rskj-core/src/main/java/org/ethereum/listener/GasWeightedCalc.java b/rskj-core/src/main/java/org/ethereum/listener/WeightedPercentileGasPriceCalculator.java
similarity index 51%
rename from rskj-core/src/main/java/org/ethereum/listener/GasWeightedCalc.java
rename to rskj-core/src/main/java/org/ethereum/listener/WeightedPercentileGasPriceCalculator.java
index 85a23ff027b..8c2af3ea886 100644
--- a/rskj-core/src/main/java/org/ethereum/listener/GasWeightedCalc.java
+++ b/rskj-core/src/main/java/org/ethereum/listener/WeightedPercentileGasPriceCalculator.java
@@ -1,7 +1,6 @@
 /*
  * This file is part of RskJ
  * Copyright (C) 2024 RSK Labs Ltd.
- * (derived from ethereumJ library, Copyright (c) 2016 <ether.camp>)
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published by
@@ -16,7 +15,6 @@
  * You should have received a copy of the GNU Lesser General Public License
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
-
 package org.ethereum.listener;
 
 import co.rsk.core.Coin;
@@ -27,73 +25,78 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.math.BigDecimal;
 import java.util.*;
 
-public class GasWeightedCalc implements GasCalculator {
-    private static final Logger logger = LoggerFactory.getLogger("gaspricetracker");
+public class WeightedPercentileGasPriceCalculator implements GasPriceCalculator {
+
+    private static final Logger logger = LoggerFactory.getLogger("wpGasPriceTracker");
     private static final int WINDOW_SIZE = 512;
-    private final Deque<GasEntry> gasWindow = new ArrayDeque<>(WINDOW_SIZE);
-    private final Map<Coin, Long> windowMap = new HashMap<>();
+    public static final int REFERENCE_PERCENTILE = 25;
+
+    private final ArrayDeque<GasEntry> gasWindow;
+    private final WeightedPercentileCalc auxCalculator;
+
     private int txCount = 0;
     private Coin cachedGasPrice = null;
 
+    public WeightedPercentileGasPriceCalculator() {
+        this(new WeightedPercentileCalc());
+    }
+
+    public WeightedPercentileGasPriceCalculator(WeightedPercentileCalc weightedPercentileCalc) {
+        auxCalculator = weightedPercentileCalc;
+        gasWindow = new ArrayDeque<>(WINDOW_SIZE);
+    }
+
+    @Override
+    public Optional<Coin> getGasPrice() {
+        if (cachedGasPrice == null) {
+            cachedGasPrice = calculateGasPrice();
+        }
+        return cachedGasPrice == null ? Optional.empty() : Optional.of(cachedGasPrice);
+    }
+
+    @Override
     public synchronized void onBlock(Block block, List<TransactionReceipt> receipts) {
-        for(TransactionReceipt receipt : receipts) {
+        for (TransactionReceipt receipt : receipts) {
             if (!(receipt.getTransaction() instanceof RemascTransaction)) {
                 addTx(receipt.getTransaction(), new Coin(receipt.getGasUsed()).asBigInteger().longValue());
             }
         }
     }
 
+    @Override
+    public GasCalculatorType getType() {
+        return GasCalculatorType.WEIGHTED_PERCENTILE;
+    }
+
     private void addTx(Transaction tx, long gasUsed) {
+        if (gasUsed == 0) {
+            return;
+        }
+
         txCount++;
 
         Coin gasPrice = tx.getGasPrice();
 
         if (gasWindow.size() == WINDOW_SIZE) {
-            GasEntry entry = gasWindow.removeFirst();
-            long value = windowMap.get(entry.gasPrice) - entry.gasUsed;
-            if (value > 0) {
-                windowMap.put(entry.gasPrice, value);
-            } else {
-                windowMap.remove(entry.gasPrice);
-            }
-        }
+            gasWindow.removeFirst();
 
+        }
         gasWindow.add(new GasEntry(gasPrice, gasUsed));
-        windowMap.merge(gasPrice, gasUsed, Long::sum);
 
-        if (txCount >= WINDOW_SIZE) {
+        if (txCount > WINDOW_SIZE) {
             txCount = 0; // Reset the count
             cachedGasPrice = calculateGasPrice();
-            logger.info("Updated gas price -> {}",cachedGasPrice);
+            logger.debug("Updated gas price -> {}", cachedGasPrice);
         }
     }
 
-    private synchronized Coin calculateGasPrice() {
-        double weightedSum = 0;
-        double totalGasUsed = 0;
-        for(Map.Entry<Coin,Long> entry : windowMap.entrySet()) {
-            weightedSum += entry.getKey().asBigInteger().doubleValue() * entry.getValue();
-            totalGasUsed += entry.getValue();
-        }
-
-        if (totalGasUsed > 0) {
-            double result = weightedSum / totalGasUsed;
-            return new Coin(BigDecimal.valueOf(result).toBigInteger());
-        }
-        return null;
-    }
-
-    public synchronized Optional<Coin> getGasPrice() {
-        if(cachedGasPrice == null) {
-            cachedGasPrice = calculateGasPrice();
-        }
-        return cachedGasPrice == null ? Optional.empty() : Optional.of(cachedGasPrice);
+    private Coin calculateGasPrice() {
+        return auxCalculator.calculateWeightedPercentile(REFERENCE_PERCENTILE, new ArrayList<>(gasWindow));
     }
 
-    static class GasEntry {
+    static class GasEntry implements Comparable<GasEntry> {
         protected Coin gasPrice;
         protected long gasUsed;
 
@@ -101,5 +104,43 @@ static class GasEntry {
             this.gasPrice = gasPrice;
             this.gasUsed = gasUsed;
         }
+
+
+        public Coin getGasPrice() {
+            return gasPrice;
+        }
+
+        public long getGasUsed() {
+            return gasUsed;
+        }
+
+        @Override
+        public int compareTo
+                (GasEntry o) {
+            return this.gasPrice.compareTo(o.gasPrice);
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (!(o instanceof GasEntry)) {
+                return false;
+            }
+            GasEntry gasEntry = (GasEntry) o;
+            return gasUsed == gasEntry.gasUsed &&
+                    Objects.equals(gasPrice, gasEntry.gasPrice);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(gasPrice, gasUsed);
+        }
+
+        @Override
+        public String toString() {
+            return "(" + gasPrice + ", " + gasUsed + ")";
+        }
     }
 }
diff --git a/rskj-core/src/main/resources/reference.conf b/rskj-core/src/main/resources/reference.conf
index c0d6c4ddae3..a84e13aa5f9 100644
--- a/rskj-core/src/main/resources/reference.conf
+++ b/rskj-core/src/main/resources/reference.conf
@@ -165,7 +165,7 @@ peer {
 miner {
     # The default gas price
     minGasPrice = 0
-    gasPriceCalculatorType = LEGACY
+    gasPriceCalculatorType = PLAIN_PERCENTILE
     server {
         enabled = false
         isFixedClock = false
diff --git a/rskj-core/src/test/java/org/ethereum/listener/GasPriceTrackerTest.java b/rskj-core/src/test/java/org/ethereum/listener/GasPriceTrackerTest.java
index 35e9134cd6d..09f4fe85c09 100644
--- a/rskj-core/src/test/java/org/ethereum/listener/GasPriceTrackerTest.java
+++ b/rskj-core/src/test/java/org/ethereum/listener/GasPriceTrackerTest.java
@@ -194,6 +194,20 @@ void isFeeMarketWorking_trueWhenAboveAverage() {
         assertTrue(gasPriceTracker.isFeeMarketWorking());
     }
 
+    @Test
+    void gasTrackerIsCreatedWithTheCorrectType(){
+        GasPriceTracker gasPriceTracker = GasPriceTracker.create(blockStore);
+        assertEquals(GasPriceCalculator.GasCalculatorType.PLAIN_PERCENTILE, gasPriceTracker.getGasCalculatorType(), "Plain pecentile is the default one");
+
+        assertEquals(GasPriceCalculator.GasCalculatorType.PLAIN_PERCENTILE,
+                GasPriceTracker.create(blockStore, GasPriceCalculator.GasCalculatorType.PLAIN_PERCENTILE).getGasCalculatorType(),
+                "Plain percentile type is expected when passed as parameter");
+
+        assertEquals(GasPriceCalculator.GasCalculatorType.WEIGHTED_PERCENTILE,
+                GasPriceTracker.create(blockStore, GasPriceCalculator.GasCalculatorType.WEIGHTED_PERCENTILE).getGasCalculatorType(),
+                "Weighted percentile type is expected when passed as parameter");
+    }
+
     private static Block makeBlock(Coin mgp, int txCount, Function<Integer, Transaction> txMaker) {
         Block block = mock(Block.class);
 
diff --git a/rskj-core/src/test/java/org/ethereum/listener/GasWeightedCalcTest.java b/rskj-core/src/test/java/org/ethereum/listener/GasWeightedCalcTest.java
deleted file mode 100644
index 7c2b44b7d04..00000000000
--- a/rskj-core/src/test/java/org/ethereum/listener/GasWeightedCalcTest.java
+++ /dev/null
@@ -1,143 +0,0 @@
-package org.ethereum.listener;
-
-import co.rsk.core.Coin;
-import org.ethereum.core.Block;
-import org.ethereum.core.Transaction;
-import org.ethereum.core.TransactionReceipt;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.mockito.Mockito;
-
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Optional;
-
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.Mockito.when;
-
-class GasWeightedCalcTest {
-
-    private GasWeightedCalc gasWeightedCalc;
-    private static final int WINDOW_SIZE = 512;
-
-    @BeforeEach
-    void setUp() {
-        gasWeightedCalc = new GasWeightedCalc();
-    }
-
-    @Test
-    void testCalculateGasPriceWithNoTransactions() {
-        // Test when no transactions are added
-        Block mockBlock = Mockito.mock(Block.class);
-
-        gasWeightedCalc.onBlock(mockBlock, new ArrayList<>());
-
-        Optional<Coin> gasPrice = gasWeightedCalc.getGasPrice();
-        assertFalse(gasPrice.isPresent(), "Gas price should not be present when no transactions are added");
-    }
-
-    @Test
-    void testCalculateGasPriceWithSingleTransaction() {
-        // Test when a single transaction is added
-        Block mockBlock = Mockito.mock(Block.class);
-
-        TransactionReceipt mockReceipt = Mockito.mock(TransactionReceipt.class);
-        Transaction mockTransaction = Mockito.mock(Transaction.class);
-        when(mockTransaction.getGasPrice()).thenReturn(new Coin(BigInteger.valueOf(100)));
-        when(mockReceipt.getTransaction()).thenReturn(mockTransaction);
-        when(mockReceipt.getGasUsed()).thenReturn(BigInteger.valueOf(500).toByteArray());
-
-        gasWeightedCalc.onBlock(mockBlock, Collections.singletonList(mockReceipt));
-
-        Optional<Coin> gasPrice = gasWeightedCalc.getGasPrice();
-        assertTrue(gasPrice.isPresent(), "Gas price should be present when a transaction is added");
-        assertEquals(new Coin(BigInteger.valueOf(100)), gasPrice.get(), "Gas price should be the same as the single transaction's gas price");
-    }
-
-    @Test
-    void testCalculateGasPriceWithMultipleTransactionsSameGasUsage() {
-        // Test when multiple transactions are added
-        Block mockBlock = Mockito.mock(Block.class);
-
-        TransactionReceipt mockReceipt1 = Mockito.mock(TransactionReceipt.class);
-        Transaction mockTransaction1 = Mockito.mock(Transaction.class);
-        when(mockTransaction1.getGasPrice()).thenReturn(new Coin(BigInteger.valueOf(100)));
-        when(mockReceipt1.getTransaction()).thenReturn(mockTransaction1);
-        when(mockReceipt1.getGasUsed()).thenReturn(BigInteger.valueOf(100).toByteArray());
-
-        TransactionReceipt mockReceipt2 = Mockito.mock(TransactionReceipt.class);
-        Transaction mockTransaction2 = Mockito.mock(Transaction.class);
-        when(mockTransaction2.getGasPrice()).thenReturn(new Coin(BigInteger.valueOf(300)));
-        when(mockReceipt2.getTransaction()).thenReturn(mockTransaction2);
-        when(mockReceipt2.getGasUsed()).thenReturn(BigInteger.valueOf(100).toByteArray());
-
-        gasWeightedCalc.onBlock(mockBlock, Arrays.asList(mockReceipt1, mockReceipt2));
-
-        Optional<Coin> gasPrice = gasWeightedCalc.getGasPrice();
-        assertEquals(new Coin(BigInteger.valueOf(200)), gasPrice.get(), "Gas price should be the weighted average of multiple transactions");
-    }
-
-    @Test
-    void testCalculateGasPriceWithMultipleTransactionsDiffGasUsage() {
-        // Test when multiple transactions are added
-        Block mockBlock = Mockito.mock(Block.class);
-
-        TransactionReceipt mockReceipt1 = Mockito.mock(TransactionReceipt.class);
-        Transaction mockTransaction1 = Mockito.mock(Transaction.class);
-        when(mockTransaction1.getGasPrice()).thenReturn(new Coin(BigInteger.valueOf(100)));
-        when(mockReceipt1.getTransaction()).thenReturn(mockTransaction1);
-        when(mockReceipt1.getGasUsed()).thenReturn(BigInteger.valueOf(100).toByteArray());
-
-        TransactionReceipt mockReceipt2 = Mockito.mock(TransactionReceipt.class);
-        Transaction mockTransaction2 = Mockito.mock(Transaction.class);
-        when(mockTransaction2.getGasPrice()).thenReturn(new Coin(BigInteger.valueOf(300)));
-        when(mockReceipt2.getTransaction()).thenReturn(mockTransaction2);
-        when(mockReceipt2.getGasUsed()).thenReturn(BigInteger.valueOf(200).toByteArray());
-
-        gasWeightedCalc.onBlock(mockBlock, Arrays.asList(mockReceipt1, mockReceipt2));
-
-        Optional<Coin> gasPrice = gasWeightedCalc.getGasPrice();
-        assertEquals(new Coin(BigInteger.valueOf(233)), gasPrice.get(), "Gas price should be the weighted average of multiple transactions");
-    }
-
-    @Test
-    void priceIsCalculatedEachWindowSize() {
-        // Test when the window size is exceeded
-        Block mockBlock = Mockito.mock(Block.class);
-
-        for (int i = 0; i < WINDOW_SIZE*2 + 1; i++) {
-            TransactionReceipt mockReceipt = Mockito.mock(TransactionReceipt.class);
-            Transaction mockTransaction = Mockito.mock(Transaction.class);
-            when(mockTransaction.getGasPrice()).thenReturn(new Coin(BigInteger.valueOf(100+(i*5))));
-            when(mockReceipt.getTransaction()).thenReturn(mockTransaction);
-            when(mockReceipt.getGasUsed()).thenReturn(BigInteger.valueOf(200+(i*10)).toByteArray());
-            gasWeightedCalc.onBlock(mockBlock, Arrays.asList(mockReceipt));
-            if(i == (WINDOW_SIZE * 2) - 2) {
-                Optional<Coin> gasPrice = gasWeightedCalc.getGasPrice();
-                assertEquals(new Coin(BigInteger.valueOf(1773)), gasPrice.get(), "Gas price won't change until next window size is reached");
-            }
-        }
-
-        Optional<Coin> gasPrice = gasWeightedCalc.getGasPrice();
-        assertEquals(new Coin(BigInteger.valueOf(4076)), gasPrice.get(), "Gas price is updated after windows size is reached");
-    }
-
-    @Test
-    void testCalculateGasPriceWithZeroTotalGasUsed() {
-        // Test when the total gas used is zero
-        Block mockBlock = Mockito.mock(Block.class);
-
-        TransactionReceipt mockReceipt = Mockito.mock(TransactionReceipt.class);
-        Transaction mockTransaction = Mockito.mock(Transaction.class);
-        when(mockTransaction.getGasPrice()).thenReturn(new Coin(BigInteger.valueOf(100)));
-        when(mockReceipt.getTransaction()).thenReturn(mockTransaction);
-        when(mockReceipt.getGasUsed()).thenReturn(BigInteger.ZERO.toByteArray());
-
-        gasWeightedCalc.onBlock(mockBlock, Collections.singletonList(mockReceipt));
-
-        Optional<Coin> gasPrice = gasWeightedCalc.getGasPrice();
-        assertFalse(gasPrice.isPresent(), "Gas price should not be present when total gas used is zero");
-    }
-}
\ No newline at end of file
diff --git a/rskj-core/src/test/java/org/ethereum/listener/WeightedPercentileCalcTest.java b/rskj-core/src/test/java/org/ethereum/listener/WeightedPercentileCalcTest.java
new file mode 100644
index 00000000000..8aea36eacad
--- /dev/null
+++ b/rskj-core/src/test/java/org/ethereum/listener/WeightedPercentileCalcTest.java
@@ -0,0 +1,76 @@
+/*
+ * This file is part of RskJ
+ * Copyright (C) 2024 RSK Labs Ltd.
+ * (derived from ethereumJ library, Copyright (c) 2016 <ether.camp>)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.ethereum.listener;
+
+import co.rsk.core.Coin;
+import org.junit.jupiter.api.Test;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class WeightedPercentileCalcTest {
+
+    @Test
+    void testCalculateWeightedPercentile() {
+        WeightedPercentileCalc weightedPercentileCalc = new WeightedPercentileCalc();
+
+        // Sample gas entries with smaller numbers
+        WeightedPercentileGasPriceCalculator.GasEntry entry1 = new WeightedPercentileGasPriceCalculator.GasEntry(new Coin(BigInteger.valueOf(100)), 1);
+        WeightedPercentileGasPriceCalculator.GasEntry entry2 = new WeightedPercentileGasPriceCalculator.GasEntry(new Coin(BigInteger.valueOf(200)), 3);
+        WeightedPercentileGasPriceCalculator.GasEntry entry3 = new WeightedPercentileGasPriceCalculator.GasEntry(new Coin(BigInteger.valueOf(300)), 1);
+        WeightedPercentileGasPriceCalculator.GasEntry entry4 = new WeightedPercentileGasPriceCalculator.GasEntry(new Coin(BigInteger.valueOf(500)), 10);
+        WeightedPercentileGasPriceCalculator.GasEntry entry5 = new WeightedPercentileGasPriceCalculator.GasEntry(new Coin(BigInteger.valueOf(400)), 1);
+        WeightedPercentileGasPriceCalculator.GasEntry entry6 = new WeightedPercentileGasPriceCalculator.GasEntry(new Coin(BigInteger.valueOf(700)), 2);
+        WeightedPercentileGasPriceCalculator.GasEntry entry7 = new WeightedPercentileGasPriceCalculator.GasEntry(new Coin(BigInteger.valueOf(600)), 4);
+        WeightedPercentileGasPriceCalculator.GasEntry entry8 = new WeightedPercentileGasPriceCalculator.GasEntry(new Coin(BigInteger.valueOf(800)), 1);
+
+
+        List<WeightedPercentileGasPriceCalculator.GasEntry> gasEntries = Arrays.asList(entry1, entry2, entry3, entry4, entry5, entry6, entry7,entry8);
+
+
+        Coin result0 = weightedPercentileCalc.calculateWeightedPercentile(0, gasEntries);
+        assertEquals(new Coin(BigInteger.valueOf(800)), result0, "0th percentile should be 100");
+
+        Coin result10 = weightedPercentileCalc.calculateWeightedPercentile(1, gasEntries);
+        assertEquals(new Coin(BigInteger.valueOf(100)), result10, "1th percentile should be 100");
+
+        Coin result20 = weightedPercentileCalc.calculateWeightedPercentile(20.2f, gasEntries);
+        assertEquals(new Coin(BigInteger.valueOf(300)), result20, "20th percentile should be 300");
+
+        Coin result40 = weightedPercentileCalc.calculateWeightedPercentile(40, gasEntries);
+        assertEquals(new Coin(BigInteger.valueOf(500)), result40, "40th percentile should be 500");
+
+        Coin result50 = weightedPercentileCalc.calculateWeightedPercentile(50, gasEntries);
+        assertEquals(new Coin(BigInteger.valueOf(500)), result50, "50th percentile should be 500");
+
+        Coin result75 = weightedPercentileCalc.calculateWeightedPercentile(75, gasEntries);
+        assertEquals(new Coin(BigInteger.valueOf(600)), result75, "75th percentile should be 600");
+
+        Coin result90 = weightedPercentileCalc.calculateWeightedPercentile(90, gasEntries);
+        assertEquals(new Coin(BigInteger.valueOf(700)), result90, "90th percentile should be 600");
+
+        Coin result100 = weightedPercentileCalc.calculateWeightedPercentile(100, gasEntries);
+        assertEquals(new Coin(BigInteger.valueOf(800)), result100, "100th percentile should be 800");
+
+
+    }
+}
\ No newline at end of file
diff --git a/rskj-core/src/test/java/org/ethereum/listener/WeightedPercentileGasPriceCalculatorTest.java b/rskj-core/src/test/java/org/ethereum/listener/WeightedPercentileGasPriceCalculatorTest.java
new file mode 100644
index 00000000000..597f5191202
--- /dev/null
+++ b/rskj-core/src/test/java/org/ethereum/listener/WeightedPercentileGasPriceCalculatorTest.java
@@ -0,0 +1,204 @@
+/*
+ * This file is part of RskJ
+ * Copyright (C) 2024 RSK Labs Ltd.
+ * (derived from ethereumJ library, Copyright (c) 2016 <ether.camp>)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.ethereum.listener;
+
+import co.rsk.core.Coin;
+import org.ethereum.core.Block;
+import org.ethereum.core.Transaction;
+import org.ethereum.core.TransactionReceipt;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+
+import java.math.BigInteger;
+import java.util.*;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+class WeightedPercentileGasPriceCalculatorTest {
+
+    private static final int WINDOW_SIZE = 512;
+    private WeightedPercentileGasPriceCalculator weightedPercentileGasPriceCalculator;
+
+
+    @BeforeEach
+    void setup() {
+        weightedPercentileGasPriceCalculator = new WeightedPercentileGasPriceCalculator();
+    }
+
+    @Test
+    void testCalculateWeightedPercentileWithNoTransactions() {
+        // Test when no transactions are added
+        assertNotNull(weightedPercentileGasPriceCalculator);
+        assertFalse(weightedPercentileGasPriceCalculator.getGasPrice().isPresent(), "Gas price should not be present when no transactions are added");
+    }
+
+    @Test
+    void testCalculateGasPriceWithZeroTotalGasUsed() {
+        // Test when the total gas used is zero
+        Block mockBlock = Mockito.mock(Block.class);
+
+        TransactionReceipt mockReceipt = Mockito.mock(TransactionReceipt.class);
+        Transaction mockTransaction = Mockito.mock(Transaction.class);
+        when(mockTransaction.getGasPrice()).thenReturn(new Coin(BigInteger.valueOf(100)));
+        when(mockReceipt.getTransaction()).thenReturn(mockTransaction);
+        when(mockReceipt.getGasUsed()).thenReturn(BigInteger.ZERO.toByteArray());
+
+        weightedPercentileGasPriceCalculator.onBlock(mockBlock, Collections.singletonList(mockReceipt));
+
+        Optional<Coin> gasPrice = weightedPercentileGasPriceCalculator.getGasPrice();
+        assertFalse(gasPrice.isPresent(), "Gas price should not be present when total gas used is zero");
+    }
+
+    @Test
+    void testCalculateGasPriceWithSingleTransaction() {
+        // Test when a single transaction is added
+        Block mockBlock = Mockito.mock(Block.class);
+
+        TransactionReceipt mockReceipt = Mockito.mock(TransactionReceipt.class);
+        Transaction mockTransaction = Mockito.mock(Transaction.class);
+        when(mockTransaction.getGasPrice()).thenReturn(new Coin(BigInteger.valueOf(100)));
+        when(mockReceipt.getTransaction()).thenReturn(mockTransaction);
+        when(mockReceipt.getGasUsed()).thenReturn(BigInteger.valueOf(500).toByteArray());
+
+        weightedPercentileGasPriceCalculator.onBlock(mockBlock, Collections.singletonList(mockReceipt));
+
+        Optional<Coin> gasPrice = weightedPercentileGasPriceCalculator.getGasPrice();
+        assertTrue(gasPrice.isPresent(), "Gas price should be present when a transaction is added");
+        assertEquals(new Coin(BigInteger.valueOf(100)), gasPrice.get(), "Gas price should be the same as the single transaction's gas price");
+    }
+
+    @Test
+    void testCalculateGasPriceWithMultipleTransactionsSameGasUsage() {
+        // Test when multiple transactions are added
+        Block mockBlock = Mockito.mock(Block.class);
+
+        TransactionReceipt mockReceipt1 = Mockito.mock(TransactionReceipt.class);
+        Transaction mockTransaction1 = Mockito.mock(Transaction.class);
+        when(mockTransaction1.getGasPrice()).thenReturn(new Coin(BigInteger.valueOf(100)));
+        when(mockReceipt1.getTransaction()).thenReturn(mockTransaction1);
+        when(mockReceipt1.getGasUsed()).thenReturn(BigInteger.valueOf(100).toByteArray());
+
+        TransactionReceipt mockReceipt2 = Mockito.mock(TransactionReceipt.class);
+        Transaction mockTransaction2 = Mockito.mock(Transaction.class);
+        when(mockTransaction2.getGasPrice()).thenReturn(new Coin(BigInteger.valueOf(300)));
+        when(mockReceipt2.getTransaction()).thenReturn(mockTransaction2);
+        when(mockReceipt2.getGasUsed()).thenReturn(BigInteger.valueOf(300).toByteArray());
+
+        TransactionReceipt mockReceipt3 = Mockito.mock(TransactionReceipt.class);
+        Transaction mockTransaction3 = Mockito.mock(Transaction.class);
+        when(mockTransaction3.getGasPrice()).thenReturn(new Coin(BigInteger.valueOf(200)));
+        when(mockReceipt3.getTransaction()).thenReturn(mockTransaction3);
+        when(mockReceipt3.getGasUsed()).thenReturn(BigInteger.valueOf(200).toByteArray());
+        weightedPercentileGasPriceCalculator.onBlock(mockBlock, Arrays.asList(mockReceipt1, mockReceipt2, mockReceipt3));
+
+        Optional<Coin> gasPrice = weightedPercentileGasPriceCalculator.getGasPrice();
+        assertTrue(gasPrice.isPresent(), "Gas price should be present when multiple transactions are added");
+        assertEquals(new Coin(BigInteger.valueOf(200)), gasPrice.get(), "Expecting 200 as weighted percentile for the provided set.");
+    }
+
+    @Test
+    void testCalculateGasPriceWithPlainSet() {
+        Block mockBlock = Mockito.mock(Block.class);
+        List<TransactionReceipt> receipts = createMockReceipts(100, 1);
+        weightedPercentileGasPriceCalculator.onBlock(mockBlock, receipts);
+        Optional<Coin> gasPrice = weightedPercentileGasPriceCalculator.getGasPrice();
+        assertTrue(gasPrice.isPresent(), "Gas price should be present when multiple transactions are added");
+        assertEquals(new Coin(BigInteger.valueOf(25)), gasPrice.get(), "Gas price should be the weighted average of multiple transactions");
+    }
+
+    @Test
+    void cacheValueIsNotUpdatedUntilWindowSizeIsReached() {
+        WeightedPercentileCalc percentileCalc = new WeightedPercentileCalc();
+        WeightedPercentileCalc spy = spy(percentileCalc);
+        WeightedPercentileGasPriceCalculator gasPriceCalculator = new WeightedPercentileGasPriceCalculator(spy);
+
+        Block mockBlock = Mockito.mock(Block.class);
+        gasPriceCalculator.onBlock(mockBlock, createMockReceipts(10, 1));
+
+        Optional<Coin> result1 = gasPriceCalculator.getGasPrice();
+        assertTrue(result1.isPresent(), "Gas price should be present when multiple transactions are added");
+
+        gasPriceCalculator.onBlock(mockBlock, createMockReceipts(WINDOW_SIZE - 20, 2));
+        Optional<Coin> result2 = gasPriceCalculator.getGasPrice();
+        assertTrue(result2.isPresent(), "Gas price should be present when multiple transactions are added");
+
+        assertEquals(result1.get(), result2.get(), "Gas price is not updated if window threshold is not reached");
+        verify(spy, times(1)).calculateWeightedPercentile(anyFloat(), anyList());
+
+        gasPriceCalculator.onBlock(mockBlock, createMockReceipts(30, 1));
+        Optional<Coin> result3 = gasPriceCalculator.getGasPrice();
+        assertTrue(result3.isPresent(), "Gas price should be present when multiple transactions are added");
+
+        assertNotEquals(result1.get(), result3.get(), "Gas price is updated if window threshold is reached");
+        verify(spy, times(2)).calculateWeightedPercentile(anyFloat(), anyList());
+    }
+
+    @Test
+    void olderTxAreRemovedWhenWindowLimitIsReach() {
+        Block mockBlock = Mockito.mock(Block.class);
+        WeightedPercentileCalc mockPC = Mockito.mock(WeightedPercentileCalc.class);
+        when(mockPC.calculateWeightedPercentile(anyFloat(), anyList())).thenReturn(new Coin(BigInteger.valueOf(1)));
+
+        ArgumentCaptor<List<WeightedPercentileGasPriceCalculator.GasEntry>> captor = ArgumentCaptor.forClass(List.class);
+        WeightedPercentileGasPriceCalculator gpc = new WeightedPercentileGasPriceCalculator(mockPC);
+
+        //Transactions are added until window size limit
+        gpc.onBlock(mockBlock, createMockReceipts(WINDOW_SIZE, 1));
+        gpc.getGasPrice();
+
+        //New transactions are added to reach the window limit and re-calculate gas
+        TransactionReceipt mockReceipt = Mockito.mock(TransactionReceipt.class);
+        Transaction mockTransaction = Mockito.mock(Transaction.class);
+        when(mockTransaction.getGasPrice()).thenReturn(new Coin(BigInteger.valueOf(850)));
+        when(mockReceipt.getTransaction()).thenReturn(mockTransaction);
+        when(mockReceipt.getGasUsed()).thenReturn(BigInteger.valueOf(1).toByteArray());
+        gpc.onBlock(mockBlock, Collections.singletonList(mockReceipt));
+        gpc.getGasPrice();
+
+        verify(mockPC, times(2)).calculateWeightedPercentile(anyFloat(), captor.capture());
+        List<List<WeightedPercentileGasPriceCalculator.GasEntry>> gasPriceList = captor.getAllValues();
+
+        List<WeightedPercentileGasPriceCalculator.GasEntry> firstList = gasPriceList.get(0);
+        Coin firstValueFirstList = firstList.get(0).getGasPrice();
+
+        assertEquals(new Coin(BigInteger.valueOf(1)), firstValueFirstList, "Gas price should be the same as the first transaction's gas price");
+
+        List<WeightedPercentileGasPriceCalculator.GasEntry> secondList = gasPriceList.get(1);
+        //The second time the getGasPrice is called the first transaction should be removed and the new one added at the bottom
+        assertEquals(new Coin(BigInteger.valueOf(850)), secondList.get(secondList.size() - 1).getGasPrice(), "Gas price should be the same as the first transaction's gas price");
+        assertEquals(firstList.subList(1, firstList.size() - 1), secondList.subList(0, secondList.size() - 2), "The first list should be the same as the second list without the first and last element");
+    }
+
+    private List<TransactionReceipt> createMockReceipts(int numOfReceipts, int gasUsed) {
+        List<TransactionReceipt> receipts = new ArrayList<>();
+        for (int i = 0; i < numOfReceipts; i++) {
+            TransactionReceipt mockReceipt = Mockito.mock(TransactionReceipt.class);
+            Transaction mockTransaction = Mockito.mock(Transaction.class);
+            when(mockTransaction.getGasPrice()).thenReturn(new Coin(BigInteger.valueOf(1 + i)));
+            when(mockReceipt.getTransaction()).thenReturn(mockTransaction);
+            when(mockReceipt.getGasUsed()).thenReturn(BigInteger.valueOf(gasUsed).toByteArray());
+            receipts.add(mockReceipt);
+        }
+        return receipts;
+    }
+
+}
\ No newline at end of file