diff --git a/CHANGELOG.md b/CHANGELOG.md
index 84c7f5f7c40..fe2d341a3d7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -30,6 +30,7 @@
 - Add support for EIP-7702 transaction in the txpool [#8018](https://github.com/hyperledger/besu/pull/8018) [#7984](https://github.com/hyperledger/besu/pull/7984)
 - Add support for `movePrecompileToAddress` in `StateOverrides` (`eth_call`)[8115](https://github.com/hyperledger/besu/pull/8115)
 - Default target-gas-limit to 36M for holesky [#8125](https://github.com/hyperledger/besu/pull/8125)
+- Add EIP-7623 - Increase calldata cost [#8093](https://github.com/hyperledger/besu/pull/8093)
 
 ### Bug fixes
 - Fix serialization of state overrides when `movePrecompileToAddress` is present [#8204](https://github.com/hyperledger/besu/pull/8024)
diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/PluginEeaSendRawTransaction.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/PluginEeaSendRawTransaction.java
index 146ef2c722d..2d6af314fc6 100644
--- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/PluginEeaSendRawTransaction.java
+++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/PluginEeaSendRawTransaction.java
@@ -84,6 +84,6 @@ protected long getGasLimit(final PrivateTransaction privateTransaction, final St
     // choose the highest of the two options
     return Math.max(
         privateTransaction.getGasLimit(),
-        gasCalculator.transactionIntrinsicGasCost(Bytes.fromBase64String(pmtPayload), false));
+        gasCalculator.transactionIntrinsicGasCost(Bytes.fromBase64String(pmtPayload), false, 0));
   }
 }
diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java
index 708dd33a29f..a2526707950 100644
--- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java
+++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java
@@ -18,6 +18,7 @@
 import static org.hyperledger.besu.ethereum.mainnet.PrivateStateUtils.KEY_PRIVATE_METADATA_UPDATER;
 import static org.hyperledger.besu.ethereum.mainnet.PrivateStateUtils.KEY_TRANSACTION;
 import static org.hyperledger.besu.ethereum.mainnet.PrivateStateUtils.KEY_TRANSACTION_HASH;
+import static org.hyperledger.besu.evm.internal.Words.clampedAdd;
 
 import org.hyperledger.besu.collections.trie.BytesTrieSet;
 import org.hyperledger.besu.datatypes.AccessListEntry;
@@ -351,22 +352,22 @@ public TransactionProcessingResult processTransaction(
         warmAddressList.add(miningBeneficiary);
       }
 
-      final long intrinsicGas =
-          gasCalculator.transactionIntrinsicGasCost(
-              transaction.getPayload(), transaction.isContractCreation());
       final long accessListGas =
           gasCalculator.accessListGasCost(accessListEntries.size(), accessListStorageCount);
       final long codeDelegationGas =
           gasCalculator.delegateCodeGasCost(transaction.codeDelegationListSize());
-      final long gasAvailable =
-          transaction.getGasLimit() - intrinsicGas - accessListGas - codeDelegationGas;
+      final long intrinsicGas =
+          gasCalculator.transactionIntrinsicGasCost(
+              transaction.getPayload(),
+              transaction.isContractCreation(),
+              clampedAdd(accessListGas, codeDelegationGas));
+
+      final long gasAvailable = transaction.getGasLimit() - intrinsicGas;
       LOG.trace(
-          "Gas available for execution {} = {} - {} - {} - {} (limit - intrinsic - accessList - codeDelegation)",
+          "Gas available for execution {} = {} - {} (limit - intrinsic)",
           gasAvailable,
           transaction.getGasLimit(),
-          intrinsicGas,
-          accessListGas,
-          codeDelegationGas);
+          intrinsicGas);
 
       final WorldUpdater worldUpdater = evmWorldUpdater.updater();
       final ImmutableMap.Builder<String, Object> contextVariablesBuilder =
@@ -438,7 +439,16 @@ public TransactionProcessingResult processTransaction(
                 .inputData(transaction.getPayload())
                 .code(
                     maybeContract
-                        .map(c -> messageCallProcessor.getCodeFromEVM(c.getCodeHash(), c.getCode()))
+                        .map(
+                            c -> {
+                              if (c.hasDelegatedCode()) {
+                                return messageCallProcessor.getCodeFromEVM(
+                                    c.getDelegatedCodeHash().get(), c.getDelegatedCode().get());
+                              }
+
+                              return messageCallProcessor.getCodeFromEVM(
+                                  c.getCodeHash(), c.getCode());
+                            })
                         .orElse(CodeV0.EMPTY_CODE))
                 .accessListWarmAddresses(warmAddressList)
                 .build();
diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java
index 2b9fea0f3d0..0bef4d569f1 100644
--- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java
+++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java
@@ -15,6 +15,8 @@
 package org.hyperledger.besu.ethereum.mainnet;
 
 import static org.hyperledger.besu.evm.account.Account.MAX_NONCE;
+import static org.hyperledger.besu.evm.internal.Words.clampedAdd;
+import static org.hyperledger.besu.evm.worldstate.DelegateCodeHelper.hasDelegatedCode;
 
 import org.hyperledger.besu.crypto.SECPSignature;
 import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
@@ -32,7 +34,6 @@
 import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
 import org.hyperledger.besu.evm.account.Account;
 import org.hyperledger.besu.evm.gascalculator.GasCalculator;
-import org.hyperledger.besu.evm.worldstate.DelegatedCodeService;
 
 import java.math.BigInteger;
 import java.util.List;
@@ -52,8 +53,6 @@
  */
 public class MainnetTransactionValidator implements TransactionValidator {
 
-  public static final BigInteger TWO_POW_8 = BigInteger.TWO.pow(8);
-  public static final BigInteger TWO_POW_64 = BigInteger.TWO.pow(64);
   public static final BigInteger TWO_POW_256 = BigInteger.TWO.pow(256);
 
   private final GasCalculator gasCalculator;
@@ -166,9 +165,9 @@ private static ValidationResult<TransactionInvalidReason> validateCodeDelegation
             .map(
                 codeDelegations -> {
                   for (CodeDelegation codeDelegation : codeDelegations) {
-                    if (codeDelegation.chainId().compareTo(TWO_POW_64) >= 0) {
+                    if (codeDelegation.chainId().compareTo(TWO_POW_256) >= 0) {
                       throw new IllegalArgumentException(
-                          "Invalid 'chainId' value, should be < 2^64 but got "
+                          "Invalid 'chainId' value, should be < 2^256 but got "
                               + codeDelegation.chainId());
                     }
 
@@ -252,17 +251,22 @@ private ValidationResult<TransactionInvalidReason> validateCostAndFee(
       }
     }
 
-    final long intrinsicGasCost =
-        gasCalculator.transactionIntrinsicGasCost(
-                transaction.getPayload(), transaction.isContractCreation())
-            + (transaction.getAccessList().map(gasCalculator::accessListGasCost).orElse(0L))
-            + gasCalculator.delegateCodeGasCost(transaction.codeDelegationListSize());
-    if (Long.compareUnsigned(intrinsicGasCost, transaction.getGasLimit()) > 0) {
+    final long baselineGas =
+        clampedAdd(
+            transaction.getAccessList().map(gasCalculator::accessListGasCost).orElse(0L),
+            gasCalculator.delegateCodeGasCost(transaction.codeDelegationListSize()));
+    final long intrinsicGasCostOrFloor =
+        Math.max(
+            gasCalculator.transactionIntrinsicGasCost(
+                transaction.getPayload(), transaction.isContractCreation(), baselineGas),
+            gasCalculator.transactionFloorCost(transaction.getPayload()));
+
+    if (Long.compareUnsigned(intrinsicGasCostOrFloor, transaction.getGasLimit()) > 0) {
       return ValidationResult.invalid(
           TransactionInvalidReason.INTRINSIC_GAS_EXCEEDS_GAS_LIMIT,
           String.format(
               "intrinsic gas cost %s exceeds gas limit %s",
-              intrinsicGasCost, transaction.getGasLimit()));
+              intrinsicGasCostOrFloor, transaction.getGasLimit()));
     }
 
     if (transaction.calculateUpfrontGasCost(transaction.getMaxGasPrice(), Wei.ZERO, 0).bitLength()
@@ -329,8 +333,7 @@ public ValidationResult<TransactionInvalidReason> validateForSender(
   }
 
   private static boolean canSendTransaction(final Account sender, final Hash codeHash) {
-    return codeHash.equals(Hash.EMPTY)
-        || DelegatedCodeService.hasDelegatedCode(sender.getUnprocessedCode());
+    return codeHash.equals(Hash.EMPTY) || hasDelegatedCode(sender.getCode());
   }
 
   private ValidationResult<TransactionInvalidReason> validateTransactionSignature(
diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/IntrinsicGasTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/IntrinsicGasTest.java
index bb9ce2b495a..84af8547bf3 100644
--- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/IntrinsicGasTest.java
+++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/IntrinsicGasTest.java
@@ -16,15 +16,21 @@
 
 import static org.assertj.core.api.Assertions.assertThat;
 
+import org.hyperledger.besu.datatypes.AccessListEntry;
 import org.hyperledger.besu.ethereum.core.Transaction;
+import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
 import org.hyperledger.besu.ethereum.rlp.RLP;
 import org.hyperledger.besu.evm.gascalculator.FrontierGasCalculator;
 import org.hyperledger.besu.evm.gascalculator.GasCalculator;
 import org.hyperledger.besu.evm.gascalculator.IstanbulGasCalculator;
+import org.hyperledger.besu.evm.gascalculator.PragueGasCalculator;
+import org.hyperledger.besu.evm.gascalculator.ShanghaiGasCalculator;
 
+import java.util.List;
 import java.util.stream.Stream;
 
 import org.apache.tuweni.bytes.Bytes;
+import org.apache.tuweni.bytes.Bytes32;
 import org.assertj.core.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
@@ -36,6 +42,8 @@ public class IntrinsicGasTest {
   public static Stream<Arguments> data() {
     final GasCalculator frontier = new FrontierGasCalculator();
     final GasCalculator istanbul = new IstanbulGasCalculator();
+    final GasCalculator shanghai = new ShanghaiGasCalculator();
+    final GasCalculator prague = new PragueGasCalculator();
     return Stream.of(
         // EnoughGAS
         Arguments.of(
@@ -81,16 +89,36 @@ public static Stream<Arguments> data() {
         Arguments.of(
             istanbul,
             21116L,
-            "0xf87c80018261a894095e7baea6a6c7c4c2dfeb977efac326af552d870a9d00000000000000000000000000000000000000000000000000000000001ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a01fffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804"));
+            "0xf87c80018261a894095e7baea6a6c7c4c2dfeb977efac326af552d870a9d00000000000000000000000000000000000000000000000000000000001ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a01fffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804"),
+        // CallData Gas Increase
+        Arguments.of(
+            prague,
+            21116L,
+            "0xf87c80018261a894095e7baea6a6c7c4c2dfeb977efac326af552d870a9d00000000000000000000000000000000000000000000000000000000001ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a01fffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804"),
+        // AccessList
+        Arguments.of(
+            shanghai,
+            25300L,
+            "0x01f89a018001826a4094095e7baea6a6c7c4c2dfeb977efac326af552d878080f838f794a95e7baea6a6c7c4c2dfeb977efac326af552d87e1a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80a05cbd172231fc0735e0fb994dd5b1a4939170a260b36f0427a8a80866b063b948a07c230f7f578dd61785c93361b9871c0706ebfa6d06e3f4491dc9558c5202ed36"));
   }
 
   @ParameterizedTest
   @MethodSource("data")
   public void validateGasCost(
       final GasCalculator gasCalculator, final long expectedGas, final String txRlp) {
-    Transaction t = Transaction.readFrom(RLP.input(Bytes.fromHexString(txRlp)));
+    Bytes rlp = Bytes.fromHexString(txRlp);
+
+    // non-frontier transactions need to be opaque for parsing to work
+    if (rlp.get(0) > 0) {
+      final BytesValueRLPOutput output = new BytesValueRLPOutput();
+      output.writeBytes(rlp);
+      rlp = output.encoded();
+    }
+
+    Transaction t = Transaction.readFrom(RLP.input(rlp));
     Assertions.assertThat(
-            gasCalculator.transactionIntrinsicGasCost(t.getPayload(), t.isContractCreation()))
+            gasCalculator.transactionIntrinsicGasCost(
+                t.getPayload(), t.isContractCreation(), baselineGas(gasCalculator, t)))
         .isEqualTo(expectedGas);
   }
 
@@ -100,4 +128,21 @@ void dryRunDetector() {
         .withFailMessage("This test is here so gradle --dry-run executes this class")
         .isTrue();
   }
+
+  long baselineGas(final GasCalculator gasCalculator, final Transaction transaction) {
+    final List<AccessListEntry> accessListEntries = transaction.getAccessList().orElse(List.of());
+
+    int accessListStorageCount = 0;
+    for (final var entry : accessListEntries) {
+      final List<Bytes32> storageKeys = entry.storageKeys();
+      accessListStorageCount += storageKeys.size();
+    }
+    final long accessListGas =
+        gasCalculator.accessListGasCost(accessListEntries.size(), accessListStorageCount);
+
+    final long codeDelegationGas =
+        gasCalculator.delegateCodeGasCost(transaction.codeDelegationListSize());
+
+    return accessListGas + codeDelegationGas;
+  }
 }
diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidatorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidatorTest.java
index c673bf08f68..86dcc2ff6bb 100644
--- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidatorTest.java
+++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidatorTest.java
@@ -128,7 +128,27 @@ public void shouldRejectTransactionIfIntrinsicGasExceedsGasLimit() {
             .gasLimit(10)
             .chainId(Optional.empty())
             .createTransaction(senderKeys);
-    when(gasCalculator.transactionIntrinsicGasCost(any(), anyBoolean())).thenReturn(50L);
+    when(gasCalculator.transactionIntrinsicGasCost(any(), anyBoolean(), anyLong())).thenReturn(50L);
+
+    assertThat(
+            validator.validate(
+                transaction, Optional.empty(), Optional.empty(), transactionValidationParams))
+        .isEqualTo(
+            ValidationResult.invalid(TransactionInvalidReason.INTRINSIC_GAS_EXCEEDS_GAS_LIMIT));
+  }
+
+  @Test
+  public void shouldRejectTransactionIfFloorExceedsGasLimit_EIP_7623() {
+    final TransactionValidator validator =
+        createTransactionValidator(
+            gasCalculator, GasLimitCalculator.constant(), false, Optional.empty());
+    final Transaction transaction =
+        new TransactionTestFixture()
+            .gasLimit(10)
+            .chainId(Optional.empty())
+            .createTransaction(senderKeys);
+    when(gasCalculator.transactionIntrinsicGasCost(any(), anyBoolean(), anyLong())).thenReturn(5L);
+    when(gasCalculator.transactionFloorCost(any())).thenReturn(51L);
 
     assertThat(
             validator.validate(
@@ -398,7 +418,7 @@ public void shouldAcceptOnlyTransactionsInAcceptedTransactionTypes() {
                 transaction, Optional.empty(), Optional.empty(), transactionValidationParams))
         .isEqualTo(ValidationResult.invalid(INVALID_TRANSACTION_FORMAT));
 
-    when(gasCalculator.transactionIntrinsicGasCost(any(), anyBoolean())).thenReturn(0L);
+    when(gasCalculator.transactionIntrinsicGasCost(any(), anyBoolean(), anyLong())).thenReturn(0L);
 
     assertThat(
             eip1559Validator.validate(
@@ -475,7 +495,7 @@ public void shouldAcceptValidEIP1559() {
             .chainId(Optional.of(BigInteger.ONE))
             .createTransaction(senderKeys);
     final Optional<Wei> basefee = Optional.of(Wei.of(150000L));
-    when(gasCalculator.transactionIntrinsicGasCost(any(), anyBoolean())).thenReturn(50L);
+    when(gasCalculator.transactionIntrinsicGasCost(any(), anyBoolean(), anyLong())).thenReturn(50L);
 
     assertThat(
             validator.validate(transaction, basefee, Optional.empty(), transactionValidationParams))
@@ -500,7 +520,7 @@ public void shouldValidate1559TransactionWithPriceLowerThanBaseFeeForTransaction
             .type(TransactionType.EIP1559)
             .chainId(Optional.of(BigInteger.ONE))
             .createTransaction(senderKeys);
-    when(gasCalculator.transactionIntrinsicGasCost(any(), anyBoolean())).thenReturn(50L);
+    when(gasCalculator.transactionIntrinsicGasCost(any(), anyBoolean(), anyLong())).thenReturn(50L);
 
     assertThat(
             validator.validate(
diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java
index 0ff6a21da83..7dde74946a2 100644
--- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java
+++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java
@@ -402,16 +402,20 @@ public void run() {
 
       long txGas = gas;
       if (chargeIntrinsicGas) {
-        final long intrinsicGasCost =
-            protocolSpec
-                .getGasCalculator()
-                .transactionIntrinsicGasCost(tx.getPayload(), tx.isContractCreation());
-        txGas -= intrinsicGasCost;
         final long accessListCost =
             tx.getAccessList()
                 .map(list -> protocolSpec.getGasCalculator().accessListGasCost(list))
                 .orElse(0L);
-        txGas -= accessListCost;
+
+        final long delegateCodeCost =
+            protocolSpec.getGasCalculator().delegateCodeGasCost(tx.codeDelegationListSize());
+
+        final long intrinsicGasCost =
+            protocolSpec
+                .getGasCalculator()
+                .transactionIntrinsicGasCost(
+                    tx.getPayload(), tx.isContractCreation(), accessListCost + delegateCodeCost);
+        txGas -= intrinsicGasCost;
       }
 
       final EVM evm = protocolSpec.getEvm();
diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java
index 15c400bc078..7053961a125 100644
--- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java
+++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java
@@ -437,7 +437,7 @@ static T8nResult runTest(
       gasUsed += transactionGasUsed;
       long intrinsicGas =
           gasCalculator.transactionIntrinsicGasCost(
-              transaction.getPayload(), transaction.getTo().isEmpty());
+              transaction.getPayload(), transaction.getTo().isEmpty(), 0);
       TransactionReceipt receipt =
           protocolSpec
               .getTransactionReceiptFactory()
diff --git a/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/t8n/prague-deposit.json b/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/t8n/prague-deposit.json
index 6c704e0e210..58f845f5cb0 100644
--- a/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/t8n/prague-deposit.json
+++ b/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/t8n/prague-deposit.json
@@ -70,7 +70,7 @@
       },
       "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
         "nonce": "0x00",
-        "balance": "0xad78ebc5ac62000000",
+        "balance": "0xaa00be18c288efd690",
         "code": "0x",
         "storage": {}
       }
@@ -194,7 +194,7 @@
         "nonce": "0x1"
       },
       "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": {
-        "balance": "0xaa00be18c288efd690",
+        "balance": "0xa688906bd8afdfad20",
         "nonce": "0x2"
       }
     },
@@ -204,7 +204,7 @@
       "requests": [
         "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200405973070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200405973070000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030100000000000000"
       ],
-      "stateRoot": "0x6471f6d90b87f759176a0ad62a7096f69d0d24fd873bdb6b6ced57d04a71e274",
+      "stateRoot": "0xc769f83dbad9b87a209216d18c4b19cb12b61838594a2e8270898438f4e147af",
       "txRoot": "0x2b790bf82ef7259a0e4513d1b89a77d81e99672ba68758ef2ba3fde32851d023",
       "receiptsRoot": "0x9c8d7a917ecb3ff2566f264abbf39131e51b08b07eb2b69cb46989d79d985593",
       "logsHash": "0x43e31613bfefc1f55d8b3ca2b61f933f3838d523dc11cb5d7ffdd2ecf0ab5d49",
diff --git a/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/core/TransactionTest.java b/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/core/TransactionTest.java
index 9aa04bd0ffe..a3758422c4f 100644
--- a/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/core/TransactionTest.java
+++ b/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/core/TransactionTest.java
@@ -192,10 +192,13 @@ public void milestone(
 
       assertThat(transaction.getSender()).isEqualTo(expected.getSender());
       assertThat(transaction.getHash()).isEqualTo(expected.getHash());
-      final long intrinsicGasCost =
-          gasCalculator.transactionIntrinsicGasCost(
-                  transaction.getPayload(), transaction.isContractCreation())
-              + (transaction.getAccessList().map(gasCalculator::accessListGasCost).orElse(0L));
+      final long baselineGas =
+        transaction.getAccessList().map(gasCalculator::accessListGasCost).orElse(0L) +
+          gasCalculator.delegateCodeGasCost(transaction.codeDelegationListSize());
+      final long intrinsicGasCost = gasCalculator.transactionIntrinsicGasCost(
+        transaction.getPayload(),
+        transaction.isContractCreation(),
+        baselineGas);
       assertThat(intrinsicGasCost).isEqualTo(expected.getIntrinsicGas());
     } catch (final Exception e) {
       if (expected.isSucceeds()) {
diff --git a/evm/src/main/java/org/hyperledger/besu/evm/account/BaseDelegatedCodeAccount.java b/evm/src/main/java/org/hyperledger/besu/evm/account/AbstractDelegatedCodeAccount.java
similarity index 65%
rename from evm/src/main/java/org/hyperledger/besu/evm/account/BaseDelegatedCodeAccount.java
rename to evm/src/main/java/org/hyperledger/besu/evm/account/AbstractDelegatedCodeAccount.java
index 4ee28145def..2318d48650c 100644
--- a/evm/src/main/java/org/hyperledger/besu/evm/account/BaseDelegatedCodeAccount.java
+++ b/evm/src/main/java/org/hyperledger/besu/evm/account/AbstractDelegatedCodeAccount.java
@@ -16,7 +16,6 @@
 
 import org.hyperledger.besu.datatypes.Address;
 import org.hyperledger.besu.datatypes.Hash;
-import org.hyperledger.besu.datatypes.Wei;
 import org.hyperledger.besu.evm.gascalculator.GasCalculator;
 import org.hyperledger.besu.evm.worldstate.WorldUpdater;
 
@@ -24,14 +23,14 @@
 
 import org.apache.tuweni.bytes.Bytes;
 
-class BaseDelegatedCodeAccount {
+abstract class AbstractDelegatedCodeAccount implements Account {
   private final WorldUpdater worldUpdater;
   private final GasCalculator gasCalculator;
 
   /** The address of the account that has delegated code to be loaded into it. */
   protected final Address delegatedCodeAddress;
 
-  protected BaseDelegatedCodeAccount(
+  protected AbstractDelegatedCodeAccount(
       final WorldUpdater worldUpdater,
       final Address delegatedCodeAddress,
       final GasCalculator gasCalculator) {
@@ -45,7 +44,8 @@ protected BaseDelegatedCodeAccount(
    *
    * @return the delegated code.
    */
-  protected Bytes getCode() {
+  @Override
+  public Optional<Bytes> getDelegatedCode() {
     return resolveDelegatedCode();
   }
 
@@ -54,27 +54,9 @@ protected Bytes getCode() {
    *
    * @return the hash of the delegated code.
    */
-  protected Hash getCodeHash() {
-    final Bytes code = getCode();
-    return (code == null || code.isEmpty()) ? Hash.EMPTY : Hash.hash(code);
-  }
-
-  /**
-   * Returns the balance of the delegated account.
-   *
-   * @return the balance of the delegated account.
-   */
-  protected Wei getDelegatedBalance() {
-    return getDelegatedAccount().map(Account::getBalance).orElse(Wei.ZERO);
-  }
-
-  /**
-   * Returns the nonce of the delegated account.
-   *
-   * @return the nonce of the delegated account.
-   */
-  protected long getDelegatedNonce() {
-    return getDelegatedAccount().map(Account::getNonce).orElse(Account.DEFAULT_NONCE);
+  @Override
+  public Optional<Hash> getDelegatedCodeHash() {
+    return getDelegatedCode().map(Hash::hash);
   }
 
   /**
@@ -82,19 +64,27 @@ protected long getDelegatedNonce() {
    *
    * @return the address of the delegated code.
    */
-  protected Optional<Address> delegatedCodeAddress() {
+  @Override
+  public Optional<Address> delegatedCodeAddress() {
     return Optional.of(delegatedCodeAddress);
   }
 
+  @Override
+  public boolean hasDelegatedCode() {
+    return true;
+  }
+
   private Optional<Account> getDelegatedAccount() {
     return Optional.ofNullable(worldUpdater.getAccount(delegatedCodeAddress));
   }
 
-  private Bytes resolveDelegatedCode() {
-    if (gasCalculator.isPrecompile(delegatedCodeAddress)) {
-      return Bytes.EMPTY;
+  private Optional<Bytes> resolveDelegatedCode() {
+    final Optional<Account> maybeDelegatedAccount = getDelegatedAccount();
+
+    if (gasCalculator.isPrecompile(delegatedCodeAddress) || maybeDelegatedAccount.isEmpty()) {
+      return Optional.of(Bytes.EMPTY);
     }
 
-    return getDelegatedAccount().map(Account::getUnprocessedCode).orElse(Bytes.EMPTY);
+    return Optional.of(maybeDelegatedAccount.get().getCode());
   }
 }
diff --git a/evm/src/main/java/org/hyperledger/besu/evm/account/Account.java b/evm/src/main/java/org/hyperledger/besu/evm/account/Account.java
index 8a65adf617c..f0196c82766 100644
--- a/evm/src/main/java/org/hyperledger/besu/evm/account/Account.java
+++ b/evm/src/main/java/org/hyperledger/besu/evm/account/Account.java
@@ -19,8 +19,6 @@
 
 import java.util.Optional;
 
-import org.apache.tuweni.bytes.Bytes;
-
 /**
  * A world state account.
  *
@@ -71,13 +69,4 @@ default Optional<Address> delegatedCodeAddress() {
   default boolean hasDelegatedCode() {
     return false;
   }
-
-  /**
-   * Returns the code as it is stored in the trie even if it's a delegated code account.
-   *
-   * @return the code as it is stored in the trie.
-   */
-  default Bytes getUnprocessedCode() {
-    return getCode();
-  }
 }
diff --git a/evm/src/main/java/org/hyperledger/besu/evm/account/AccountState.java b/evm/src/main/java/org/hyperledger/besu/evm/account/AccountState.java
index a1bd0da1826..235f61fbe40 100644
--- a/evm/src/main/java/org/hyperledger/besu/evm/account/AccountState.java
+++ b/evm/src/main/java/org/hyperledger/besu/evm/account/AccountState.java
@@ -18,6 +18,7 @@
 import org.hyperledger.besu.datatypes.Wei;
 
 import java.util.NavigableMap;
+import java.util.Optional;
 
 import org.apache.tuweni.bytes.Bytes;
 import org.apache.tuweni.bytes.Bytes32;
@@ -74,6 +75,15 @@ public interface AccountState {
    */
   Bytes getCode();
 
+  /**
+   * The optional EVM bytecode if the account has set a 7702 code delegation.
+   *
+   * @return the delegated code (which may be empty).
+   */
+  default Optional<Bytes> getDelegatedCode() {
+    return Optional.empty();
+  }
+
   /**
    * The hash of the EVM bytecode associated with this account.
    *
@@ -81,6 +91,15 @@ public interface AccountState {
    */
   Hash getCodeHash();
 
+  /**
+   * The optional hash of the delegated EVM bytecode if the account has set a 7702 code delegation.
+   *
+   * @return the hash of the delegated code (which may be empty).
+   */
+  default Optional<Hash> getDelegatedCodeHash() {
+    return Optional.empty();
+  }
+
   /**
    * Whether the account has (non empty) EVM bytecode associated to it.
    *
diff --git a/evm/src/main/java/org/hyperledger/besu/evm/account/DelegatedCodeAccount.java b/evm/src/main/java/org/hyperledger/besu/evm/account/DelegatedCodeAccount.java
index 0ac969abade..3252dab9c21 100644
--- a/evm/src/main/java/org/hyperledger/besu/evm/account/DelegatedCodeAccount.java
+++ b/evm/src/main/java/org/hyperledger/besu/evm/account/DelegatedCodeAccount.java
@@ -28,7 +28,7 @@
 import org.apache.tuweni.units.bigints.UInt256;
 
 /** Wraps an EOA account and includes delegated code to be run on behalf of it. */
-public class DelegatedCodeAccount extends BaseDelegatedCodeAccount implements Account {
+public class DelegatedCodeAccount extends AbstractDelegatedCodeAccount implements Account {
 
   private final Account wrappedAccount;
 
@@ -81,17 +81,12 @@ public Wei getBalance() {
 
   @Override
   public Bytes getCode() {
-    return super.getCode();
-  }
-
-  @Override
-  public Bytes getUnprocessedCode() {
     return wrappedAccount.getCode();
   }
 
   @Override
   public Hash getCodeHash() {
-    return super.getCodeHash();
+    return wrappedAccount.getCodeHash();
   }
 
   @Override
@@ -106,7 +101,7 @@ public UInt256 getOriginalStorageValue(final UInt256 key) {
 
   @Override
   public boolean isEmpty() {
-    return getDelegatedNonce() == 0 && getDelegatedBalance().isZero() && !hasCode();
+    return wrappedAccount.isEmpty();
   }
 
   @Override
@@ -119,9 +114,4 @@ public NavigableMap<Bytes32, AccountStorageEntry> storageEntriesFrom(
       final Bytes32 startKeyHash, final int limit) {
     return wrappedAccount.storageEntriesFrom(startKeyHash, limit);
   }
-
-  @Override
-  public boolean hasDelegatedCode() {
-    return true;
-  }
 }
diff --git a/evm/src/main/java/org/hyperledger/besu/evm/account/MutableDelegatedCodeAccount.java b/evm/src/main/java/org/hyperledger/besu/evm/account/MutableDelegatedCodeAccount.java
index 20894b4f286..9b98d596430 100644
--- a/evm/src/main/java/org/hyperledger/besu/evm/account/MutableDelegatedCodeAccount.java
+++ b/evm/src/main/java/org/hyperledger/besu/evm/account/MutableDelegatedCodeAccount.java
@@ -29,7 +29,7 @@
 import org.apache.tuweni.units.bigints.UInt256;
 
 /** Wraps an EOA account and includes delegated code to be run on behalf of it. */
-public class MutableDelegatedCodeAccount extends BaseDelegatedCodeAccount
+public class MutableDelegatedCodeAccount extends AbstractDelegatedCodeAccount
     implements MutableAccount {
 
   private final MutableAccount wrappedAccount;
@@ -83,17 +83,12 @@ public Wei getBalance() {
 
   @Override
   public Bytes getCode() {
-    return super.getCode();
-  }
-
-  @Override
-  public Bytes getUnprocessedCode() {
     return wrappedAccount.getCode();
   }
 
   @Override
   public Hash getCodeHash() {
-    return super.getCodeHash();
+    return wrappedAccount.getCodeHash();
   }
 
   @Override
@@ -108,7 +103,7 @@ public UInt256 getOriginalStorageValue(final UInt256 key) {
 
   @Override
   public boolean isEmpty() {
-    return getDelegatedNonce() == 0 && getDelegatedBalance().isZero() && !hasCode();
+    return wrappedAccount.isEmpty();
   }
 
   @Override
@@ -156,9 +151,4 @@ public Map<UInt256, UInt256> getUpdatedStorage() {
   public void becomeImmutable() {
     wrappedAccount.becomeImmutable();
   }
-
-  @Override
-  public boolean hasDelegatedCode() {
-    return true;
-  }
 }
diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FrontierGasCalculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FrontierGasCalculator.java
index 8db00c3dd51..efa33ceeac6 100644
--- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FrontierGasCalculator.java
+++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/FrontierGasCalculator.java
@@ -39,7 +39,8 @@ public class FrontierGasCalculator implements GasCalculator {
 
   private static final long TX_DATA_NON_ZERO_COST = 68L;
 
-  private static final long TX_BASE_COST = 21_000L;
+  /** Minimum base cost that every transaction needs to pay */
+  protected static final long TX_BASE_COST = 21_000L;
 
   private static final long TX_CREATE_EXTRA_COST = 0L;
 
@@ -129,18 +130,82 @@ public FrontierGasCalculator() {
   }
 
   @Override
-  public long transactionIntrinsicGasCost(final Bytes payload, final boolean isContractCreate) {
+  public long transactionIntrinsicGasCost(
+      final Bytes payload, final boolean isContractCreation, final long baselineGas) {
+    final long dynamicIntrinsicGasCost =
+        dynamicIntrinsicGasCost(payload, isContractCreation, baselineGas);
+
+    if (dynamicIntrinsicGasCost == Long.MIN_VALUE || dynamicIntrinsicGasCost == Long.MAX_VALUE) {
+      return dynamicIntrinsicGasCost;
+    }
+    return clampedAdd(getMinimumTransactionCost(), dynamicIntrinsicGasCost);
+  }
+
+  /**
+   * Calculates the dynamic part of the intrinsic gas cost
+   *
+   * @param payload the call data payload
+   * @param isContractCreation whether the transaction is a contract creation
+   * @param baselineGas how much gas is used by access lists and code delegations
+   * @return the dynamic part of the intrinsic gas cost
+   */
+  protected long dynamicIntrinsicGasCost(
+      final Bytes payload, final boolean isContractCreation, final long baselineGas) {
+    final int payloadSize = payload.size();
+    final long zeroBytes = zeroBytes(payload);
+    long cost = clampedAdd(callDataCost(payloadSize, zeroBytes), baselineGas);
+
+    if (cost == Long.MIN_VALUE || cost == Long.MAX_VALUE) {
+      return cost;
+    }
+
+    if (isContractCreation) {
+      cost = clampedAdd(cost, contractCreationCost(payloadSize));
+
+      if (cost == Long.MIN_VALUE || cost == Long.MAX_VALUE) {
+        return cost;
+      }
+    }
+
+    return cost;
+  }
+
+  /**
+   * Calculates the cost of the call data
+   *
+   * @param payloadSize the total size of the payload
+   * @param zeroBytes the number of zero bytes in the payload
+   * @return the cost of the call data
+   */
+  protected long callDataCost(final long payloadSize, final long zeroBytes) {
+    return clampedAdd(
+        TX_DATA_NON_ZERO_COST * (payloadSize - zeroBytes), TX_DATA_ZERO_COST * zeroBytes);
+  }
+
+  /**
+   * Counts the zero bytes in the payload
+   *
+   * @param payload the payload
+   * @return the number of zero bytes in the payload
+   */
+  protected static long zeroBytes(final Bytes payload) {
     int zeros = 0;
     for (int i = 0; i < payload.size(); i++) {
       if (payload.get(i) == 0) {
-        ++zeros;
+        zeros += 1;
       }
     }
-    final int nonZeros = payload.size() - zeros;
-
-    final long cost = TX_BASE_COST + TX_DATA_ZERO_COST * zeros + TX_DATA_NON_ZERO_COST * nonZeros;
+    return zeros;
+  }
 
-    return isContractCreate ? (cost + txCreateExtraGasCost()) : cost;
+  /**
+   * Returns the gas cost for contract creation transactions
+   *
+   * @param ignored the size of the contract creation code (ignored in Frontier)
+   * @return the gas cost for contract creation transactions
+   */
+  protected long contractCreationCost(final int ignored) {
+    return txCreateExtraGasCost();
   }
 
   /**
@@ -152,6 +217,11 @@ protected long txCreateExtraGasCost() {
     return TX_CREATE_EXTRA_COST;
   }
 
+  @Override
+  public long transactionFloorCost(final Bytes payload) {
+    return 0L;
+  }
+
   @Override
   public long codeDepositGasCost(final int codeSize) {
     return CODE_DEPOSIT_BYTE_COST * codeSize;
@@ -558,11 +628,6 @@ static long memoryCost(final long length) {
     return clampedAdd(clampedMultiply(MEMORY_WORD_GAS_COST, length), base);
   }
 
-  @Override
-  public long getMaximumTransactionCost(final int size) {
-    return TX_BASE_COST + TX_DATA_NON_ZERO_COST * size;
-  }
-
   @Override
   public long getMinimumTransactionCost() {
     return TX_BASE_COST;
@@ -572,20 +637,21 @@ public long getMinimumTransactionCost() {
   public long calculateGasRefund(
       final Transaction transaction,
       final MessageFrame initialFrame,
-      final long codeDelegationRefund) {
-    final long selfDestructRefund =
-        getSelfDestructRefundAmount() * initialFrame.getSelfDestructs().size();
-    final long baseRefundGas =
-        initialFrame.getGasRefund() + selfDestructRefund + codeDelegationRefund;
-    return refunded(transaction, initialFrame.getRemainingGas(), baseRefundGas);
+      final long ignoredCodeDelegationRefund) {
+
+    final long refundAllowance = calculateRefundAllowance(transaction, initialFrame);
+
+    return initialFrame.getRemainingGas() + refundAllowance;
   }
 
-  private long refunded(
-      final Transaction transaction, final long gasRemaining, final long gasRefund) {
+  private long calculateRefundAllowance(
+      final Transaction transaction, final MessageFrame initialFrame) {
+    final long selfDestructRefund =
+        getSelfDestructRefundAmount() * initialFrame.getSelfDestructs().size();
+    final long executionRefund = initialFrame.getGasRefund() + selfDestructRefund;
     // Integer truncation takes care of the floor calculation needed after the divide.
     final long maxRefundAllowance =
-        (transaction.getGasLimit() - gasRemaining) / getMaxRefundQuotient();
-    final long refundAllowance = Math.min(maxRefundAllowance, gasRefund);
-    return gasRemaining + refundAllowance;
+        (transaction.getGasLimit() - initialFrame.getRemainingGas()) / getMaxRefundQuotient();
+    return Math.min(executionRefund, maxRefundAllowance);
   }
 }
diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/GasCalculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/GasCalculator.java
index ec8537cf9e3..9462a6f315b 100644
--- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/GasCalculator.java
+++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/GasCalculator.java
@@ -543,10 +543,21 @@ default long modExpGasCost(final Bytes input) {
    * encoded binary representation when stored on-chain.
    *
    * @param transactionPayload The encoded transaction, as bytes
-   * @param isContractCreate Is this transaction a contract creation transaction?
+   * @param isContractCreation Is this transaction a contract creation transaction?
+   * @param baselineGas The gas used by access lists and code delegation authorizations
    * @return the transaction's intrinsic gas cost
    */
-  long transactionIntrinsicGasCost(Bytes transactionPayload, boolean isContractCreate);
+  long transactionIntrinsicGasCost(
+      Bytes transactionPayload, boolean isContractCreation, long baselineGas);
+
+  /**
+   * Returns the floor gas cost of a transaction payload, i.e. the minimum gas cost that a
+   * transaction will be charged based on its calldata. Introduced in EIP-7623 in Prague.
+   *
+   * @param transactionPayload The encoded transaction, as bytes
+   * @return the transaction's floor gas cost
+   */
+  long transactionFloorCost(final Bytes transactionPayload);
 
   /**
    * Returns the gas cost of the explicitly declared access list.
@@ -580,15 +591,6 @@ default long getMaxRefundQuotient() {
     return 2;
   }
 
-  /**
-   * Maximum Cost of a Transaction of a certain length.
-   *
-   * @param size the length of the transaction, in bytes
-   * @return the maximum gas cost
-   */
-  // what would be the gas for a PMT with hash of all non-zeros
-  long getMaximumTransactionCost(int size);
-
   /**
    * Minimum gas cost of a transaction.
    *
diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/IstanbulGasCalculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/IstanbulGasCalculator.java
index a997f7fe16e..5df0c168bd3 100644
--- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/IstanbulGasCalculator.java
+++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/IstanbulGasCalculator.java
@@ -14,9 +14,10 @@
  */
 package org.hyperledger.besu.evm.gascalculator;
 
+import static org.hyperledger.besu.evm.internal.Words.clampedAdd;
+
 import java.util.function.Supplier;
 
-import org.apache.tuweni.bytes.Bytes;
 import org.apache.tuweni.units.bigints.UInt256;
 
 /** The Istanbul gas calculator. */
@@ -24,7 +25,6 @@ public class IstanbulGasCalculator extends PetersburgGasCalculator {
 
   private static final long TX_DATA_ZERO_COST = 4L;
   private static final long ISTANBUL_TX_DATA_NON_ZERO_COST = 16L;
-  private static final long TX_BASE_COST = 21_000L;
 
   private static final long SLOAD_GAS = 800L;
   private static final long BALANCE_OPERATION_GAS_COST = 700L;
@@ -42,19 +42,9 @@ public class IstanbulGasCalculator extends PetersburgGasCalculator {
   public IstanbulGasCalculator() {}
 
   @Override
-  public long transactionIntrinsicGasCost(final Bytes payload, final boolean isContractCreation) {
-    int zeros = 0;
-    for (int i = 0; i < payload.size(); i++) {
-      if (payload.get(i) == 0) {
-        ++zeros;
-      }
-    }
-    final int nonZeros = payload.size() - zeros;
-
-    final long cost =
-        TX_BASE_COST + (TX_DATA_ZERO_COST * zeros) + (ISTANBUL_TX_DATA_NON_ZERO_COST * nonZeros);
-
-    return isContractCreation ? (cost + txCreateExtraGasCost()) : cost;
+  protected long callDataCost(final long payloadSize, final long zeroBytes) {
+    return clampedAdd(
+        ISTANBUL_TX_DATA_NON_ZERO_COST * (payloadSize - zeroBytes), TX_DATA_ZERO_COST * zeroBytes);
   }
 
   @Override
@@ -136,9 +126,4 @@ public long getBalanceOperationGasCost() {
   public long extCodeHashOperationGasCost() {
     return EXTCODE_HASH_COST;
   }
-
-  @Override
-  public long getMaximumTransactionCost(final int size) {
-    return TX_BASE_COST + (ISTANBUL_TX_DATA_NON_ZERO_COST * size);
-  }
 }
diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/PragueGasCalculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/PragueGasCalculator.java
index 268a58061c7..60f2b84938e 100644
--- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/PragueGasCalculator.java
+++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/PragueGasCalculator.java
@@ -15,8 +15,13 @@
 package org.hyperledger.besu.evm.gascalculator;
 
 import static org.hyperledger.besu.datatypes.Address.BLS12_MAP_FP2_TO_G2;
+import static org.hyperledger.besu.evm.internal.Words.clampedAdd;
 
 import org.hyperledger.besu.datatypes.CodeDelegation;
+import org.hyperledger.besu.datatypes.Transaction;
+import org.hyperledger.besu.evm.frame.MessageFrame;
+
+import org.apache.tuweni.bytes.Bytes;
 
 /**
  * Gas Calculator for Prague
@@ -26,6 +31,8 @@
  * </UL>
  */
 public class PragueGasCalculator extends CancunGasCalculator {
+  private static final long TOTAL_COST_FLOOR_PER_TOKEN = 10L;
+
   final long existingAccountGasRefund;
 
   /**
@@ -68,4 +75,47 @@ public long delegateCodeGasCost(final int delegateCodeListLength) {
   public long calculateDelegateCodeGasRefund(final long alreadyExistingAccounts) {
     return existingAccountGasRefund * alreadyExistingAccounts;
   }
+
+  @Override
+  public long calculateGasRefund(
+      final Transaction transaction,
+      final MessageFrame initialFrame,
+      final long codeDelegationRefund) {
+
+    final long refundAllowance =
+        calculateRefundAllowance(transaction, initialFrame, codeDelegationRefund);
+
+    final long executionGasUsed =
+        transaction.getGasLimit() - initialFrame.getRemainingGas() - refundAllowance;
+    final long transactionFloorCost = transactionFloorCost(transaction.getPayload());
+    final long totalGasUsed = Math.max(executionGasUsed, transactionFloorCost);
+    return transaction.getGasLimit() - totalGasUsed;
+  }
+
+  private long calculateRefundAllowance(
+      final Transaction transaction,
+      final MessageFrame initialFrame,
+      final long codeDelegationRefund) {
+    final long selfDestructRefund =
+        getSelfDestructRefundAmount() * initialFrame.getSelfDestructs().size();
+    final long executionRefund =
+        initialFrame.getGasRefund() + selfDestructRefund + codeDelegationRefund;
+    // Integer truncation takes care of the floor calculation needed after the divide.
+    final long maxRefundAllowance =
+        (transaction.getGasLimit() - initialFrame.getRemainingGas()) / getMaxRefundQuotient();
+    return Math.min(executionRefund, maxRefundAllowance);
+  }
+
+  @Override
+  public long transactionFloorCost(final Bytes transactionPayload) {
+    return clampedAdd(
+        getMinimumTransactionCost(),
+        tokensInCallData(transactionPayload.size(), zeroBytes(transactionPayload))
+            * TOTAL_COST_FLOOR_PER_TOKEN);
+  }
+
+  private long tokensInCallData(final long payloadSize, final long zeroBytes) {
+    // as defined in https://eips.ethereum.org/EIPS/eip-7623#specification
+    return clampedAdd(zeroBytes, (payloadSize - zeroBytes) * 4);
+  }
 }
diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/ShanghaiGasCalculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/ShanghaiGasCalculator.java
index a44300f06a3..aa0dd080dd6 100644
--- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/ShanghaiGasCalculator.java
+++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/ShanghaiGasCalculator.java
@@ -14,11 +14,8 @@
  */
 package org.hyperledger.besu.evm.gascalculator;
 
-import static org.hyperledger.besu.evm.internal.Words.clampedAdd;
 import static org.hyperledger.besu.evm.internal.Words.numWords;
 
-import org.apache.tuweni.bytes.Bytes;
-
 /** The Shanghai gas calculator. */
 public class ShanghaiGasCalculator extends LondonGasCalculator {
 
@@ -39,13 +36,8 @@ public ShanghaiGasCalculator() {
   }
 
   @Override
-  public long transactionIntrinsicGasCost(final Bytes payload, final boolean isContractCreation) {
-    long intrinsicGasCost = super.transactionIntrinsicGasCost(payload, isContractCreation);
-    if (isContractCreation) {
-      return clampedAdd(intrinsicGasCost, initcodeCost(payload.size()));
-    } else {
-      return intrinsicGasCost;
-    }
+  protected long contractCreationCost(final int initCodeLength) {
+    return txCreateExtraGasCost() + initcodeCost(initCodeLength);
   }
 
   @Override
diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCallOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCallOperation.java
index 932bb4c3915..d2cde85a62f 100644
--- a/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCallOperation.java
+++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCallOperation.java
@@ -15,7 +15,6 @@
 package org.hyperledger.besu.evm.operation;
 
 import static org.hyperledger.besu.evm.internal.Words.clampedToLong;
-import static org.hyperledger.besu.evm.worldstate.DelegatedCodeGasCostHelper.deductDelegatedCodeGasCost;
 
 import org.hyperledger.besu.datatypes.Address;
 import org.hyperledger.besu.datatypes.Wei;
@@ -192,13 +191,24 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) {
 
     final Account contract = frame.getWorldUpdater().get(to);
 
-    if (contract != null) {
-      final DelegatedCodeGasCostHelper.Result result =
-          deductDelegatedCodeGasCost(frame, gasCalculator(), contract);
-      if (result.status() != DelegatedCodeGasCostHelper.Status.SUCCESS) {
+    if (contract != null && contract.hasDelegatedCode()) {
+      if (contract.getDelegatedCode().isEmpty()) {
+        throw new RuntimeException("A delegated code account must have delegated code");
+      }
+
+      if (contract.getDelegatedCodeHash().isEmpty()) {
+        throw new RuntimeException("A delegated code account must have a delegated code hash");
+      }
+
+      final long delegatedCodeResolutionGas =
+          DelegatedCodeGasCostHelper.delegatedCodeGasCost(frame, gasCalculator(), contract);
+
+      if (frame.getRemainingGas() < delegatedCodeResolutionGas) {
         return new Operation.OperationResult(
-            result.gasCost(), ExceptionalHaltReason.INSUFFICIENT_GAS);
+            delegatedCodeResolutionGas, ExceptionalHaltReason.INSUFFICIENT_GAS);
       }
+
+      frame.decrementRemainingGas(delegatedCodeResolutionGas);
     }
 
     final Account account = frame.getWorldUpdater().get(frame.getRecipientAddress());
@@ -218,10 +228,7 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) {
 
     final Bytes inputData = frame.readMutableMemory(inputDataOffset(frame), inputDataLength(frame));
 
-    final Code code =
-        contract == null
-            ? CodeV0.EMPTY_CODE
-            : evm.getCode(contract.getCodeHash(), contract.getCode());
+    final Code code = getCode(evm, contract);
 
     // invalid code results in a quick exit
     if (!code.isValid()) {
@@ -337,4 +344,23 @@ Bytes getCallResultStackItem(final MessageFrame childFrame) {
       return LEGACY_FAILURE_STACK_ITEM;
     }
   }
+
+  /**
+   * Gets the code from the contract or EOA with delegated code.
+   *
+   * @param evm the evm
+   * @param account the account which needs to be retrieved
+   * @return the code
+   */
+  protected static Code getCode(final EVM evm, final Account account) {
+    if (account == null) {
+      return CodeV0.EMPTY_CODE;
+    }
+
+    if (account.hasDelegatedCode()) {
+      return evm.getCode(account.getDelegatedCodeHash().get(), account.getDelegatedCode().get());
+    }
+
+    return evm.getCode(account.getCodeHash(), account.getCode());
+  }
 }
diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractExtCallOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractExtCallOperation.java
index 2c80007c769..1040cb1a86f 100644
--- a/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractExtCallOperation.java
+++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractExtCallOperation.java
@@ -15,14 +15,12 @@
 package org.hyperledger.besu.evm.operation;
 
 import static org.hyperledger.besu.evm.internal.Words.clampedAdd;
-import static org.hyperledger.besu.evm.worldstate.DelegatedCodeGasCostHelper.deductDelegatedCodeGasCost;
 
 import org.hyperledger.besu.datatypes.Address;
 import org.hyperledger.besu.datatypes.Wei;
 import org.hyperledger.besu.evm.Code;
 import org.hyperledger.besu.evm.EVM;
 import org.hyperledger.besu.evm.account.Account;
-import org.hyperledger.besu.evm.code.CodeV0;
 import org.hyperledger.besu.evm.frame.ExceptionalHaltReason;
 import org.hyperledger.besu.evm.frame.MessageFrame;
 import org.hyperledger.besu.evm.gascalculator.GasCalculator;
@@ -127,13 +125,24 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) {
     Address to = Words.toAddress(toBytes);
     final Account contract = frame.getWorldUpdater().get(to);
 
-    if (contract != null) {
-      final DelegatedCodeGasCostHelper.Result result =
-          deductDelegatedCodeGasCost(frame, gasCalculator, contract);
-      if (result.status() != DelegatedCodeGasCostHelper.Status.SUCCESS) {
+    if (contract != null && contract.hasDelegatedCode()) {
+      if (contract.getDelegatedCode().isEmpty()) {
+        throw new RuntimeException("A delegated code account must have delegated code");
+      }
+
+      if (contract.getDelegatedCodeHash().isEmpty()) {
+        throw new RuntimeException("A delegated code account must have a delegated code hash");
+      }
+
+      final long delegatedCodeResolutionGas =
+          DelegatedCodeGasCostHelper.delegatedCodeGasCost(frame, gasCalculator(), contract);
+
+      if (frame.getRemainingGas() < delegatedCodeResolutionGas) {
         return new Operation.OperationResult(
-            result.gasCost(), ExceptionalHaltReason.INSUFFICIENT_GAS);
+            delegatedCodeResolutionGas, ExceptionalHaltReason.INSUFFICIENT_GAS);
       }
+
+      frame.decrementRemainingGas(delegatedCodeResolutionGas);
     }
 
     boolean accountCreation = (contract == null || contract.isEmpty()) && !zeroValue;
@@ -154,10 +163,7 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) {
     currentGas -= cost;
     frame.expandMemory(inputOffset, inputLength);
 
-    final Code code =
-        contract == null
-            ? CodeV0.EMPTY_CODE
-            : evm.getCode(contract.getCodeHash(), contract.getCode());
+    final Code code = getCode(evm, contract);
 
     // invalid code results in a quick exit
     if (!code.isValid()) {
diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeCopyOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeCopyOperation.java
index ed1e4697778..848cfaaeaa0 100644
--- a/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeCopyOperation.java
+++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeCopyOperation.java
@@ -16,7 +16,6 @@
 
 import static org.hyperledger.besu.evm.internal.Words.clampedAdd;
 import static org.hyperledger.besu.evm.internal.Words.clampedToLong;
-import static org.hyperledger.besu.evm.worldstate.DelegatedCodeGasCostHelper.deductDelegatedCodeGasCost;
 
 import org.hyperledger.besu.datatypes.Address;
 import org.hyperledger.besu.evm.EVM;
@@ -26,7 +25,7 @@
 import org.hyperledger.besu.evm.frame.MessageFrame;
 import org.hyperledger.besu.evm.gascalculator.GasCalculator;
 import org.hyperledger.besu.evm.internal.Words;
-import org.hyperledger.besu.evm.worldstate.DelegatedCodeGasCostHelper;
+import org.hyperledger.besu.evm.worldstate.DelegateCodeHelper;
 
 import org.apache.tuweni.bytes.Bytes;
 
@@ -96,16 +95,7 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) {
 
     final Account account = frame.getWorldUpdater().get(address);
 
-    if (account != null) {
-      final DelegatedCodeGasCostHelper.Result result =
-          deductDelegatedCodeGasCost(frame, gasCalculator(), account);
-      if (result.status() != DelegatedCodeGasCostHelper.Status.SUCCESS) {
-        return new Operation.OperationResult(
-            result.gasCost(), ExceptionalHaltReason.INSUFFICIENT_GAS);
-      }
-    }
-
-    final Bytes code = account != null ? account.getCode() : Bytes.EMPTY;
+    final Bytes code = getCode(account);
 
     if (enableEIP3540
         && code.size() >= 2
@@ -118,4 +108,14 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) {
 
     return new OperationResult(cost, null);
   }
+
+  private static Bytes getCode(final Account account) {
+    if (account == null) {
+      return Bytes.EMPTY;
+    }
+
+    return account.hasDelegatedCode()
+        ? DelegateCodeHelper.getDelegatedCodeForRead()
+        : account.getCode();
+  }
 }
diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeHashOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeHashOperation.java
index 9a8cfe83865..9157c55aa05 100644
--- a/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeHashOperation.java
+++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeHashOperation.java
@@ -14,8 +14,6 @@
  */
 package org.hyperledger.besu.evm.operation;
 
-import static org.hyperledger.besu.evm.worldstate.DelegatedCodeGasCostHelper.deductDelegatedCodeGasCost;
-
 import org.hyperledger.besu.datatypes.Address;
 import org.hyperledger.besu.datatypes.Hash;
 import org.hyperledger.besu.evm.EVM;
@@ -27,7 +25,7 @@
 import org.hyperledger.besu.evm.internal.OverflowException;
 import org.hyperledger.besu.evm.internal.UnderflowException;
 import org.hyperledger.besu.evm.internal.Words;
-import org.hyperledger.besu.evm.worldstate.DelegatedCodeGasCostHelper;
+import org.hyperledger.besu.evm.worldstate.DelegateCodeHelper;
 
 import org.apache.tuweni.bytes.Bytes;
 
@@ -85,19 +83,10 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) {
 
       final Account account = frame.getWorldUpdater().get(address);
 
-      if (account != null) {
-        final DelegatedCodeGasCostHelper.Result result =
-            deductDelegatedCodeGasCost(frame, gasCalculator(), account);
-        if (result.status() != DelegatedCodeGasCostHelper.Status.SUCCESS) {
-          return new Operation.OperationResult(
-              result.gasCost(), ExceptionalHaltReason.INSUFFICIENT_GAS);
-        }
-      }
-
       if (account == null || account.isEmpty()) {
         frame.pushStackItem(Bytes.EMPTY);
       } else {
-        final Bytes code = account.getCode();
+        final Bytes code = getCode(account);
         if (enableEIP3540
             && code.size() >= 2
             && code.get(0) == EOFLayout.EOF_PREFIX_BYTE
@@ -115,4 +104,12 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) {
       return new OperationResult(cost(true), ExceptionalHaltReason.TOO_MANY_STACK_ITEMS);
     }
   }
+
+  private static Bytes getCode(final Account account) {
+    if (!account.hasDelegatedCode()) {
+      return account.getCode();
+    }
+
+    return DelegateCodeHelper.getDelegatedCodeForRead();
+  }
 }
diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeSizeOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeSizeOperation.java
index c2795f364b0..8b8ff172542 100644
--- a/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeSizeOperation.java
+++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/ExtCodeSizeOperation.java
@@ -14,8 +14,6 @@
  */
 package org.hyperledger.besu.evm.operation;
 
-import static org.hyperledger.besu.evm.worldstate.DelegatedCodeGasCostHelper.deductDelegatedCodeGasCost;
-
 import org.hyperledger.besu.datatypes.Address;
 import org.hyperledger.besu.evm.EVM;
 import org.hyperledger.besu.evm.account.Account;
@@ -26,7 +24,7 @@
 import org.hyperledger.besu.evm.internal.OverflowException;
 import org.hyperledger.besu.evm.internal.UnderflowException;
 import org.hyperledger.besu.evm.internal.Words;
-import org.hyperledger.besu.evm.worldstate.DelegatedCodeGasCostHelper;
+import org.hyperledger.besu.evm.worldstate.DelegateCodeHelper;
 
 import org.apache.tuweni.bytes.Bytes;
 
@@ -82,20 +80,11 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) {
       } else {
         final Account account = frame.getWorldUpdater().get(address);
 
-        if (account != null) {
-          final DelegatedCodeGasCostHelper.Result result =
-              deductDelegatedCodeGasCost(frame, gasCalculator(), account);
-          if (result.status() != DelegatedCodeGasCostHelper.Status.SUCCESS) {
-            return new Operation.OperationResult(
-                result.gasCost(), ExceptionalHaltReason.INSUFFICIENT_GAS);
-          }
-        }
-
         Bytes codeSize;
         if (account == null) {
           codeSize = Bytes.EMPTY;
         } else {
-          final Bytes code = account.getCode();
+          final Bytes code = getCode(account);
           if (enableEIP3540
               && code.size() >= 2
               && code.get(0) == EOFLayout.EOF_PREFIX_BYTE
@@ -114,4 +103,14 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) {
       return new OperationResult(cost(true), ExceptionalHaltReason.TOO_MANY_STACK_ITEMS);
     }
   }
+
+  private static Bytes getCode(final Account account) {
+    if (account == null) {
+      return Bytes.EMPTY;
+    }
+
+    return account.hasDelegatedCode()
+        ? DelegateCodeHelper.getDelegatedCodeForRead()
+        : account.getCode();
+  }
 }
diff --git a/evm/src/main/java/org/hyperledger/besu/evm/worldstate/DelegateCodeHelper.java b/evm/src/main/java/org/hyperledger/besu/evm/worldstate/DelegateCodeHelper.java
new file mode 100644
index 00000000000..5331bdd2757
--- /dev/null
+++ b/evm/src/main/java/org/hyperledger/besu/evm/worldstate/DelegateCodeHelper.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright contributors to Hyperledger Besu.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+package org.hyperledger.besu.evm.worldstate;
+
+import org.hyperledger.besu.datatypes.Address;
+
+import org.apache.tuweni.bytes.Bytes;
+
+/** Helper class for 7702 delegated code interactions */
+public class DelegateCodeHelper {
+  /**
+   * The designator that is returned when a ExtCode* operation calls a contract with delegated code
+   */
+  public static final Bytes DELEGATED_CODE_DESIGNATOR = Bytes.fromHexString("ef01");
+
+  /** The prefix that is used to identify delegated code */
+  public static final Bytes DELEGATED_CODE_PREFIX = Bytes.fromHexString("ef0100");
+
+  /** The size of the delegated code */
+  public static final int DELEGATED_CODE_SIZE = DELEGATED_CODE_PREFIX.size() + Address.SIZE;
+
+  /** create a new DelegateCodeHelper */
+  public DelegateCodeHelper() {
+    // empty
+  }
+
+  /**
+   * Returns if the provided code is delegated code.
+   *
+   * @param code the code to check.
+   * @return {@code true} if the code is delegated code, {@code false} otherwise.
+   */
+  public static boolean hasDelegatedCode(final Bytes code) {
+    return code != null
+        && code.size() == DELEGATED_CODE_SIZE
+        && code.slice(0, DELEGATED_CODE_PREFIX.size()).equals(DELEGATED_CODE_PREFIX);
+  }
+
+  /**
+   * Returns the delegated code designator
+   *
+   * @return the hardcoded designator for delegated code: ef01
+   */
+  public static Bytes getDelegatedCodeForRead() {
+    return DELEGATED_CODE_DESIGNATOR;
+  }
+}
diff --git a/evm/src/main/java/org/hyperledger/besu/evm/worldstate/DelegatedCodeGasCostHelper.java b/evm/src/main/java/org/hyperledger/besu/evm/worldstate/DelegatedCodeGasCostHelper.java
index 3cdd2dc205d..480dc8fcb67 100644
--- a/evm/src/main/java/org/hyperledger/besu/evm/worldstate/DelegatedCodeGasCostHelper.java
+++ b/evm/src/main/java/org/hyperledger/besu/evm/worldstate/DelegatedCodeGasCostHelper.java
@@ -33,22 +33,6 @@ private DelegatedCodeGasCostHelper() {
     // empty constructor
   }
 
-  /** The status of the operation. */
-  public enum Status {
-    /** The operation failed due to insufficient gas. */
-    INSUFFICIENT_GAS,
-    /** The operation was successful. */
-    SUCCESS
-  }
-
-  /**
-   * The result of the operation.
-   *
-   * @param gasCost the gas cost
-   * @param status of the operation
-   */
-  public record Result(long gasCost, Status status) {}
-
   /**
    * Deducts the gas cost for delegated code resolution.
    *
@@ -57,26 +41,18 @@ public record Result(long gasCost, Status status) {}
    * @param account the account
    * @return the gas cost and result of the operation
    */
-  public static Result deductDelegatedCodeGasCost(
+  public static long delegatedCodeGasCost(
       final MessageFrame frame, final GasCalculator gasCalculator, final Account account) {
     if (!account.hasDelegatedCode()) {
-      return new Result(0, Status.SUCCESS);
+      return 0;
     }
 
     if (account.delegatedCodeAddress().isEmpty()) {
       throw new RuntimeException("A delegated code account must have a delegated code address");
     }
 
-    final long delegatedCodeResolutionGas =
-        calculateDelegatedCodeResolutionGas(
-            frame, gasCalculator, account.delegatedCodeAddress().get());
-
-    if (frame.getRemainingGas() < delegatedCodeResolutionGas) {
-      return new Result(delegatedCodeResolutionGas, Status.INSUFFICIENT_GAS);
-    }
-
-    frame.decrementRemainingGas(delegatedCodeResolutionGas);
-    return new Result(delegatedCodeResolutionGas, Status.SUCCESS);
+    return calculateDelegatedCodeResolutionGas(
+        frame, gasCalculator, account.delegatedCodeAddress().get());
   }
 
   private static long calculateDelegatedCodeResolutionGas(
diff --git a/evm/src/main/java/org/hyperledger/besu/evm/worldstate/DelegatedCodeService.java b/evm/src/main/java/org/hyperledger/besu/evm/worldstate/DelegatedCodeService.java
index 770d0b79ddc..d919b9dc691 100644
--- a/evm/src/main/java/org/hyperledger/besu/evm/worldstate/DelegatedCodeService.java
+++ b/evm/src/main/java/org/hyperledger/besu/evm/worldstate/DelegatedCodeService.java
@@ -14,6 +14,9 @@
  */
 package org.hyperledger.besu.evm.worldstate;
 
+import static org.hyperledger.besu.evm.worldstate.DelegateCodeHelper.DELEGATED_CODE_PREFIX;
+import static org.hyperledger.besu.evm.worldstate.DelegateCodeHelper.hasDelegatedCode;
+
 import org.hyperledger.besu.datatypes.Address;
 import org.hyperledger.besu.evm.account.Account;
 import org.hyperledger.besu.evm.account.DelegatedCodeAccount;
@@ -25,8 +28,6 @@
 
 /** A service that manages the code injection of delegated code. */
 public class DelegatedCodeService {
-  private static final Bytes DELEGATED_CODE_PREFIX = Bytes.fromHexString("ef0100");
-  private static final int DELEGATED_CODE_SIZE = DELEGATED_CODE_PREFIX.size() + Address.SIZE;
 
   private final GasCalculator gasCalculator;
 
@@ -64,7 +65,7 @@ public void processDelegatedCodeAuthorization(
    * @return {@code true} if the account can set delegated code, {@code false} otherwise.
    */
   public boolean canSetDelegatedCode(final Account account) {
-    return account.getCode().isEmpty() || hasDelegatedCode(account.getUnprocessedCode());
+    return account.getCode().isEmpty() || hasDelegatedCode(account.getCode());
   }
 
   /**
@@ -102,18 +103,6 @@ public MutableAccount processMutableAccount(
         worldUpdater, account, resolveDelegatedAddress(account.getCode()), gasCalculator);
   }
 
-  /**
-   * Returns if the provided code is delegated code.
-   *
-   * @param code the code to check.
-   * @return {@code true} if the code is delegated code, {@code false} otherwise.
-   */
-  public static boolean hasDelegatedCode(final Bytes code) {
-    return code != null
-        && code.size() == DELEGATED_CODE_SIZE
-        && code.slice(0, DELEGATED_CODE_PREFIX.size()).equals(DELEGATED_CODE_PREFIX);
-  }
-
   private Address resolveDelegatedAddress(final Bytes code) {
     return Address.wrap(code.slice(DELEGATED_CODE_PREFIX.size()));
   }
diff --git a/evm/src/test/java/org/hyperledger/besu/evm/gascalculator/FrontierGasCalculatorTest.java b/evm/src/test/java/org/hyperledger/besu/evm/gascalculator/FrontierGasCalculatorTest.java
index a657776b843..b0b949d3823 100644
--- a/evm/src/test/java/org/hyperledger/besu/evm/gascalculator/FrontierGasCalculatorTest.java
+++ b/evm/src/test/java/org/hyperledger/besu/evm/gascalculator/FrontierGasCalculatorTest.java
@@ -51,11 +51,11 @@ void shouldCalculateRefundWithNoSelfDestructs() {
 
     // Assert
     assertThat(refund)
-        .isEqualTo(6500L); // 5000 (remaining) + min(1500 (total refund), 19000 (max allowance))
+        .isEqualTo(6000L); // 5000 (remaining) + min(1000 (execution refund), 47500 (max allowance))
   }
 
   @Test
-  void shouldCalculateRefundWithMultipleSelfDestructs() {
+  void shouldCalculateRefundWithMultipleSelfDestructsAndIgnoreCodeDelegation() {
     // Arrange
     Set<Address> selfDestructs = new HashSet<>();
     selfDestructs.add(Address.wrap(Bytes.random(20)));
@@ -71,7 +71,8 @@ void shouldCalculateRefundWithMultipleSelfDestructs() {
 
     // Assert
     assertThat(refund)
-        .isEqualTo(52500L); // 5000 (remaining) + min(47500 (total refund), 49500 (max allowance))
+        .isEqualTo(
+            52500L); // 5000 (remaining) + min(49500 (execution refund), 47500 (max allowance))
   }
 
   @Test
@@ -87,7 +88,8 @@ void shouldRespectMaxRefundAllowance() {
 
     // Assert
     assertThat(refund)
-        .isEqualTo(60000L); // 20000 (remaining) + min(101000 (total refund), 40000 (max allowance))
+        .isEqualTo(
+            60000L); // 20000 (remaining) + min(101000 (execution refund), 40000 (max allowance))
   }
 
   @Test
@@ -99,9 +101,23 @@ void shouldHandleZeroValuesCorrectly() {
     when(transaction.getGasLimit()).thenReturn(100000L);
 
     // Act
-    long refund = gasCalculator.calculateGasRefund(transaction, messageFrame, 0L);
+    long refund =
+        gasCalculator.calculateGasRefund(
+            transaction,
+            messageFrame,
+            0L); // 0 (remaining) + min(0 (execution refund), 50000 (max allowance))
 
     // Assert
     assertThat(refund).isEqualTo(0L);
   }
+
+  @Test
+  void transactionFloorCostShouldAlwaysBeZero() {
+    assertThat(gasCalculator.transactionFloorCost(Bytes.EMPTY)).isEqualTo(0L);
+    assertThat(gasCalculator.transactionFloorCost(Bytes.random(256))).isEqualTo(0L);
+    assertThat(gasCalculator.transactionFloorCost(Bytes.repeat((byte) 0x0, Integer.MAX_VALUE)))
+        .isEqualTo(0L);
+    assertThat(gasCalculator.transactionFloorCost(Bytes.repeat((byte) 0x1, Integer.MAX_VALUE)))
+        .isEqualTo(0L);
+  }
 }
diff --git a/evm/src/test/java/org/hyperledger/besu/evm/gascalculator/PragueGasCalculatorTest.java b/evm/src/test/java/org/hyperledger/besu/evm/gascalculator/PragueGasCalculatorTest.java
index fdacad0e84e..e8ded745859 100644
--- a/evm/src/test/java/org/hyperledger/besu/evm/gascalculator/PragueGasCalculatorTest.java
+++ b/evm/src/test/java/org/hyperledger/besu/evm/gascalculator/PragueGasCalculatorTest.java
@@ -15,22 +15,36 @@
 package org.hyperledger.besu.evm.gascalculator;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.when;
 
 import org.hyperledger.besu.datatypes.Address;
+import org.hyperledger.besu.datatypes.Transaction;
+import org.hyperledger.besu.evm.frame.MessageFrame;
 
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
+import org.apache.tuweni.bytes.Bytes;
+import org.assertj.core.api.AssertionsForClassTypes;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.TestInstance;
+import org.junit.jupiter.api.extension.ExtendWith;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.Arguments;
 import org.junit.jupiter.params.provider.MethodSource;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
 
 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
+@ExtendWith(MockitoExtension.class)
 class PragueGasCalculatorTest {
 
   private static final long TARGET_BLOB_GAS_PER_BLOCK_PRAGUE = 0xC0000;
   private final PragueGasCalculator pragueGasCalculator = new PragueGasCalculator();
+  @Mock private Transaction transaction;
+  @Mock private MessageFrame messageFrame;
 
   @Test
   void testPrecompileSize() {
@@ -66,4 +80,125 @@ Iterable<Arguments> blobGasses() {
             pragueGasCalculator.getBlobGasPerBlob()),
         Arguments.of(sixBlobTargetGas, newTargetCount, sixBlobTargetGas));
   }
+
+  @Test
+  void shouldCalculateRefundWithCodeDelegationAndNoSelfDestructs() {
+    // Arrange
+    when(messageFrame.getSelfDestructs()).thenReturn(Collections.emptySet());
+    when(messageFrame.getGasRefund()).thenReturn(1000L);
+    when(messageFrame.getRemainingGas()).thenReturn(5000L);
+    when(transaction.getGasLimit()).thenReturn(100000L);
+    when(transaction.getPayload()).thenReturn(Bytes.EMPTY);
+
+    // Act
+    long refund = pragueGasCalculator.calculateGasRefund(transaction, messageFrame, 500L);
+
+    // Assert
+    // execution refund = 1000 + 0 (self destructs) + 500 (code delegation) = 1500
+    AssertionsForClassTypes.assertThat(refund)
+        .isEqualTo(6500L); // 5000 (remaining) + min(1500 (execution refund), 19000 (max allowance))
+  }
+
+  @Test
+  void shouldCalculateRefundWithMultipleSelfDestructs() {
+    // Arrange
+    Set<Address> selfDestructs = new HashSet<>();
+    selfDestructs.add(Address.wrap(Bytes.random(20)));
+    selfDestructs.add(Address.wrap(Bytes.random(20)));
+
+    when(messageFrame.getSelfDestructs()).thenReturn(selfDestructs);
+    when(messageFrame.getGasRefund()).thenReturn(1000L);
+    when(messageFrame.getRemainingGas()).thenReturn(5000L);
+    when(transaction.getGasLimit()).thenReturn(100000L);
+    when(transaction.getPayload()).thenReturn(Bytes.EMPTY);
+
+    // Act
+    long refund = pragueGasCalculator.calculateGasRefund(transaction, messageFrame, 1000L);
+
+    // Assert
+    // execution refund = 1000 + 0 (self destructs EIP-3529) + 1000 (code delegation) = 2000
+    AssertionsForClassTypes.assertThat(refund)
+        .isEqualTo(7000L); // 5000 (remaining) + min(2000 (execution refund), 1900 (max allowance))
+  }
+
+  @Test
+  void shouldRespectMaxRefundAllowance() {
+    // Arrange
+    when(messageFrame.getSelfDestructs()).thenReturn(Collections.emptySet());
+    when(messageFrame.getGasRefund()).thenReturn(100000L);
+    when(messageFrame.getRemainingGas()).thenReturn(20000L);
+    when(transaction.getGasLimit()).thenReturn(100000L);
+    when(transaction.getPayload()).thenReturn(Bytes.EMPTY);
+
+    // Act
+    long refund = pragueGasCalculator.calculateGasRefund(transaction, messageFrame, 1000L);
+
+    // Assert
+    // execution refund = 100000 + 1000 (code delegation) = 101000
+    AssertionsForClassTypes.assertThat(refund)
+        .isEqualTo(
+            36000L); // 20000 (remaining) + min(101000 (execution refund), 16000 (max allowance))
+  }
+
+  @Test
+  void shouldHandleZeroValuesCorrectly() {
+    // Arrange
+    when(messageFrame.getSelfDestructs()).thenReturn(Collections.emptySet());
+    when(messageFrame.getGasRefund()).thenReturn(0L);
+    when(messageFrame.getRemainingGas()).thenReturn(0L);
+    when(transaction.getGasLimit()).thenReturn(100000L);
+    when(transaction.getPayload()).thenReturn(Bytes.EMPTY);
+
+    // Act
+    long refund =
+        pragueGasCalculator.calculateGasRefund(
+            transaction,
+            messageFrame,
+            0L); // 0 (remaining) + min(0 (execution refund), 20000 (max allowance))
+
+    // Assert
+    AssertionsForClassTypes.assertThat(refund).isEqualTo(0L);
+  }
+
+  @Test
+  void shouldRespectTransactionFloorCost() {
+    // Arrange
+    when(messageFrame.getSelfDestructs()).thenReturn(Collections.emptySet());
+    when(messageFrame.getGasRefund()).thenReturn(100000L);
+    when(messageFrame.getRemainingGas()).thenReturn(90000L);
+    when(transaction.getGasLimit()).thenReturn(100000L);
+    when(transaction.getPayload()).thenReturn(Bytes.EMPTY);
+
+    // Act
+    long refund = pragueGasCalculator.calculateGasRefund(transaction, messageFrame, 1000L);
+
+    // Assert
+    // refund allowance = 16000
+    // execution gas used = 100000 (gas limit) - 20000 (remaining gas) - 16000 (refund allowance) =
+    // 64000
+    // floor cost = 21000 (base cost) + 0 (tokensInCallData * floor cost per token) = 21000
+    AssertionsForClassTypes.assertThat(refund)
+        .isEqualTo(
+            79000L); // 100000 (gas limit) - max(8000 (execution gas used), 21000 (floor cost))
+  }
+
+  @Test
+  void transactionFloorCostShouldBeAtLeastTransactionBaseCost() {
+    // floor cost = 21000 (base cost) + 0
+    AssertionsForClassTypes.assertThat(pragueGasCalculator.transactionFloorCost(Bytes.EMPTY))
+        .isEqualTo(21000);
+    // floor cost = 21000 (base cost) + 256 (tokensInCallData) * 10 (cost per token)
+    AssertionsForClassTypes.assertThat(
+            pragueGasCalculator.transactionFloorCost(Bytes.repeat((byte) 0x0, 256)))
+        .isEqualTo(23560L);
+    // floor cost = 21000 (base cost) + 256 * 4 (tokensInCallData) * 10 (cost per token)
+    AssertionsForClassTypes.assertThat(
+            pragueGasCalculator.transactionFloorCost(Bytes.repeat((byte) 0x1, 256)))
+        .isEqualTo(31240L);
+    // floor cost = 21000 (base cost) + 5 + (6 * 4) (tokensInCallData) * 10 (cost per token)
+    AssertionsForClassTypes.assertThat(
+            pragueGasCalculator.transactionFloorCost(
+                Bytes.fromHexString("0x0001000100010001000101")))
+        .isEqualTo(21290L);
+  }
 }