diff --git a/geth-utils/gethutil/mpt/witness/extension_node.go b/geth-utils/gethutil/mpt/witness/extension_node.go
index e61c01f4f6..fee54ac26a 100644
--- a/geth-utils/gethutil/mpt/witness/extension_node.go
+++ b/geth-utils/gethutil/mpt/witness/extension_node.go
@@ -15,11 +15,11 @@ func prepareExtensions(extNibbles []byte, proofEl1, proofEl2 []byte) (byte, []by
 	numberOfNibbles := getExtensionNumberOfNibbles(proofEl1)
 
 	// We need nibbles as witness to compute key RLC, so we set them
-	// into extensionRowC s_advices (we can do this because both extension
+	// into extensionRowC (we can do this because both extension
 	// nodes have the same key, so we can have this info only in one).
 	// There can be more up to 64 nibbles, but there is only 32 bytes
-	// in extensionRowC s_advices. So we store every second nibble (having
-	// the whole byte and one nibble is enough to compute the other nibble).
+	// in extensionRowC. So we store every second nibble (having
+	// the byte and one nibble is enough to compute the other nibble).
 
 	startNibblePos := 2 // we don't need any nibbles for case keyLen = 1
 	if keyLen > 1 {
@@ -31,8 +31,7 @@ func prepareExtensions(extNibbles []byte, proofEl1, proofEl2 []byte) (byte, []by
 	}
 	ind := 0
 	for j := startNibblePos; j < len(extNibbles); j += 2 {
-		v3[2+ind] = // TODO: check 2 + ind
-			extNibbles[j]
+		v3[2+ind] = extNibbles[j]
 		ind++
 	}
 	values = append(values, v1)
diff --git a/geth-utils/gethutil/mpt/witness/leaf.go b/geth-utils/gethutil/mpt/witness/leaf.go
index bed72053e3..88cdb89980 100644
--- a/geth-utils/gethutil/mpt/witness/leaf.go
+++ b/geth-utils/gethutil/mpt/witness/leaf.go
@@ -580,13 +580,41 @@ func prepareStorageLeafNode(leafS, leafC, constructedLeaf, neighbourNode []byte,
 	return node
 }
 
-func equipLeafWithWrongExtension(leafNode Node, keyBefore, keyMiddle, keyAfter []byte) Node {
+func equipLeafWithWrongExtension(leafNode Node, keyBefore, keyMiddle, keyAfter, nibblesMiddle, nibblesAfter []byte) Node {
 	l := len(leafNode.Values)
 	// The rows which are used for nibbles (it means there are checks for values being < 16)
 	// in the modified extension node cases are omitted.
 	leafNode.Values[l-modifiedExtensionNodeRowLen - 1] = keyBefore
+
 	leafNode.Values[l-modifiedExtensionNodeRowLen] = keyMiddle
+	startNibblePos := 2 // we don't need any nibbles for case keyLen = 1
+	if len(keyMiddle) > 1 {
+		if len(nibblesMiddle) % 2 == 0 {
+			startNibblePos = 1
+		} else {
+			startNibblePos = 2
+		}
+	}
+	ind := 0
+	for j := startNibblePos; j < len(nibblesMiddle); j += 2 {
+		leafNode.Values[l-modifiedExtensionNodeRowLen + 1][2+ind] = nibblesMiddle[j]
+		ind++
+	}
+
 	leafNode.Values[l-modifiedExtensionNodeRowLen + 3] = keyAfter
+	startNibblePos = 2 // we don't need any nibbles for case keyLen = 1
+	if len(keyAfter) > 1 {
+		if len(nibblesAfter) % 2 == 0 {
+			startNibblePos = 1
+		} else {
+			startNibblePos = 2
+		}
+	}
+	ind = 0
+	for j := startNibblePos; j < len(nibblesAfter); j += 2 {
+		leafNode.Values[l-modifiedExtensionNodeRowLen + 4][2+ind] = nibblesAfter[j]
+		ind++
+	}
 
 	return leafNode
 }
\ No newline at end of file
diff --git a/geth-utils/gethutil/mpt/witness/prepare_witness.go b/geth-utils/gethutil/mpt/witness/prepare_witness.go
index 70b2e4342d..f3db30a932 100644
--- a/geth-utils/gethutil/mpt/witness/prepare_witness.go
+++ b/geth-utils/gethutil/mpt/witness/prepare_witness.go
@@ -1,7 +1,6 @@
 package witness
 
 import (
-	"fmt"
 	"math/big"
 
 	"main/gethutil/mpt/oracle"
@@ -517,22 +516,19 @@ func convertProofToWitness(statedb *state.StateDB, addr common.Address, addrh []
 				
 				start := keyIndex - len(nibbles)
 
-				before := newKey[0:start]
-				if len(before) % 2 == 1 {
-					before = append(before, 0)
+				nibblesBefore := newKey[0:start]
+				if len(nibblesBefore) % 2 == 1 {
+					nibblesBefore = append(nibblesBefore, 0)
 				}
-				keyBefore := trie.HexToKeybytes(before)
-				fmt.Println(keyBefore)
+				keyBefore := trie.HexToKeybytes(nibblesBefore)
 
-				middle := newKey[start:keyIndex]
+				nibblesMiddle := newKey[start:keyIndex]
 				keyMiddle := []byte{160}
-				keyMiddle = append(keyMiddle, trie.HexToCompact(middle)...)
-				fmt.Println(keyMiddle)
+				keyMiddle = append(keyMiddle, trie.HexToCompact(nibblesMiddle)...)
 
-				after := newKey[keyIndex:]
+				nibblesAfter := newKey[keyIndex:len(newKey)-1] // Remove the last flag (16)
 				keyAfter := []byte{160}
-				keyAfter = append(keyAfter, trie.HexToCompact(after)...)
-				fmt.Println(keyAfter)
+				keyAfter = append(keyAfter, trie.HexToCompact(nibblesAfter)...)
 
 				isExtension := true
 				// Dummy branch. The constraint of the branch being in the extension node and the constraint of the
@@ -549,7 +545,7 @@ func convertProofToWitness(statedb *state.StateDB, addr common.Address, addrh []
 					dummyLeaf := []byte{248,108,157,52,45,53,199,120,18,165,14,109,22,4,141,198,233,128,219,44,247,218,241,231,2,206,125,246,58,246,15,3,184,76,248,74,4,134,85,156,208,108,8,0,160,86,232,31,23,27,204,85,166,255,131,69,230,146,192,248,110,91,72,224,27,153,108,173,192,1,98,47,181,227,99,180,33,160,197,210,70,1,134,247,35,60,146,126,125,178,220,199,3,192,229,0,182,83,202,130,39,59,123,250,216,4,93,133,164,112}
 					node := prepareAccountLeafNode(addr, addrh, dummyLeaf, dummyLeaf, dummyLeaf, nil, addr_nibbles, false, false, false)
 
-					node = equipLeafWithWrongExtension(node, keyBefore, keyMiddle, keyAfter)
+					node = equipLeafWithWrongExtension(node, keyBefore, keyMiddle, keyAfter, nibblesMiddle, nibblesAfter)
 
 					nodes = append(nodes, node)
 				} else {
diff --git a/zkevm-circuits/src/mpt_circuit/account_leaf.rs b/zkevm-circuits/src/mpt_circuit/account_leaf.rs
index 741867dd0a..ebac85bd67 100644
--- a/zkevm-circuits/src/mpt_circuit/account_leaf.rs
+++ b/zkevm-circuits/src/mpt_circuit/account_leaf.rs
@@ -1,5 +1,5 @@
 use eth_types::{Field, OpsIdentity, U256};
-use gadgets::util::{pow, Scalar};
+use gadgets::util::{pow, xor, Scalar};
 use halo2_proofs::{
     circuit::Value,
     plonk::{Error, Expression, VirtualCells},
@@ -16,17 +16,15 @@ use crate::{
     circuit_tools::{
         cached_region::CachedRegion,
         cell_manager::Cell,
-        constraint_builder::{RLCChainableRev, RLCable},
+        constraint_builder::{RLCChainable, RLCChainableRev, RLCable},
         gadgets::IsEqualGadget,
     },
     evm_circuit::util::from_bytes,
     mpt_circuit::{
         helpers::{
-            key_memory, main_memory, num_nibbles, parent_memory, DriftedGadget, Indexable,
-            IsPlaceholderLeafGadget, KeyData, MPTConstraintBuilder, ParentData, WrongGadget,
-            KECCAK,
+            ext_key_rlc_expr, key_memory, leaf_key_rlc, main_memory, num_nibbles, parent_memory, DriftedGadget, Indexable, IsPlaceholderLeafGadget, KeyData, MPTConstraintBuilder, ParentData, WrongGadget, KECCAK
         },
-        param::{EMPTY_TRIE_HASH, KEY_LEN_IN_NIBBLES, RLP_LIST_LONG, RLP_LONG},
+        param::{EMPTY_TRIE_HASH, KEY_LEN_IN_NIBBLES, KEY_PREFIX_ODD, RLP_LIST_LONG, RLP_LONG},
         MPTConfig, MPTContext, MptMemory, RlpItemType,
     },
     table::MPTProofType,
@@ -368,7 +366,7 @@ impl<F: Field> AccountLeafConfig<F> {
                 &cb.key_r.expr(),
             );
 
-            // Wrong leaf / extension node handling
+            // Wrong leaf handling
             config.wrong = WrongGadget::construct(
                 cb,
                 key_item.hash_rlc(),
@@ -383,30 +381,72 @@ impl<F: Field> AccountLeafConfig<F> {
                 &cb.key_r.expr(),
             );
 
-            // TODO: wrong extension node
-            /*
-            let wrong_bytes =
-                ctx.rlp_item(meta, cb, AccountRowType::Wrong as usize, RlpItemType::Key);
-            */
+            // TODO: wrong extension node gadget
             let wrong_ext_middle =
                 ctx.rlp_item(meta, cb, AccountRowType::LongExtNodeKey as usize, RlpItemType::Key);
+            let wrong_ext_middle_nibbles =
+                ctx.rlp_item(meta, cb, AccountRowType::LongExtNodeNibbles as usize, RlpItemType::Nibbles);
             let wrong_ext_after =
                 ctx.rlp_item(meta, cb, AccountRowType::ShortExtNodeKey as usize, RlpItemType::Key);
+            let wrong_ext_after_nibbles =
+                ctx.rlp_item(meta, cb, AccountRowType::ShortExtNodeNibbles as usize, RlpItemType::Nibbles);
+
+            // In the wrong extension node, AccountRowType::Wrong stores the bytes of the key nibbles
+            // up until the extension node.
+            let (mut rlc, _) = wrong_bytes.rlc_chain_data(); 
+            // The nibbles stored in the Wrong row (up until the extension node)
+            // need to be the same as the nibbles in the path.
+            require!(rlc => config.key_data_prev.rlc.expr());
+
+            // We have a key split into three parts in
+            // the wrong extension node case, meaning that there the first part parity doesn't
+            // tell us about the parity of the second part (depends on the third part as well).
+
+            let data0 = [wrong_ext_middle.clone(), wrong_ext_middle_nibbles.clone()];
+            rlc = rlc
+                + ext_key_rlc_expr(
+                    cb,
+                    wrong_ext_middle,
+                    config.key_data_prev.mult.expr(),
+                    config.key_data[1].is_odd.expr(),
+                    config.key_data_prev.is_odd.expr(),
+                    data0
+                        .iter()
+                        .map(|item| item.bytes_be())
+                        .collect::<Vec<_>>()
+                        .try_into()
+                        .unwrap(),
+                    &cb.key_r.expr(),
+                );
+
+            // odd odd -> even
+            // odd even -> odd
+            // even odd -> odd
+            // even even -> even
+            let after_two_parts_is_odd =
+                xor::expr(config.key_data_prev.is_odd.expr(), config.key_data[1].is_odd.expr());
 
-            let (before, before_mult) = wrong_bytes.rlc_chain_data(); 
-            require!(before => config.key_data_prev.rlc.expr());
+            // The total number of nibbles is odd, thus:
+            let third_part_is_odd = after_two_parts_is_odd.clone();
 
-            /*
-            wrong_ext_before = key_data[is_s.idx()].rlc.expr()
-                + rlp_key.key.expr(
+            let data1 = [wrong_ext_after.clone(), wrong_ext_after_nibbles.clone()];
+            rlc = rlc
+                + ext_key_rlc_expr(
                     cb,
-                    rlp_key.key_value.clone(),
-                    key_data[is_s.idx()].mult.expr(),
-                    key_data[is_s.idx()].is_odd.expr(),
+                    wrong_ext_after,
+                    config.key_data[1].mult.expr(),
+                    third_part_is_odd,
+                    after_two_parts_is_odd,
+                    data1
+                        .iter()
+                        .map(|item| item.bytes_be())
+                        .collect::<Vec<_>>()
+                        .try_into()
+                        .unwrap(),
                     &cb.key_r.expr(),
                 );
-            */
 
+            require!(key_item.hash_rlc() => rlc);
 
             // Anything following this node is below the account
             // TODO(Brecht): For non-existing accounts it should be impossible to prove