Repository: dusk-network/rusk (language: rust)

Issue:
node-data: remove unnecessary WrappedContractId
#### Summary

`WrappedContractId` existed mainly because of the lack of trait implementations on the foreign base type. Since serde de- & serialization is now supported on `ContractId`, we can remove `WrappedContractId`.

#### Possible Solution

Remove `WrappedContractId` & make sure `TryFrom<String>` gets implemented on `ContractId` (tracked via https://github.com/dusk-network/piecrust/issues/420)



Discussion / hints:

Fix patch:
diff --git a/Cargo.lock b/Cargo.lock
index 8fcb6c50d6..55c86ae0f1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -122,7 +122,7 @@ dependencies = [
 name = "alice"
 version = "0.3.0"
 dependencies = [
- "dusk-core 1.1.0",
+ "dusk-core",
 ]
 
 [[package]]
@@ -767,7 +767,7 @@ version = "0.3.0"
 dependencies = [
  "bytecheck",
  "dusk-bytes",
- "dusk-core 1.1.0",
+ "dusk-core",
  "rkyv",
 ]
 
@@ -887,7 +887,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 name = "charlie"
 version = "0.3.0"
 dependencies = [
- "dusk-core 1.1.0",
+ "dusk-core",
  "rkyv",
 ]
 
@@ -1618,26 +1618,6 @@ dependencies = [
  "derive-hex",
 ]
 
-[[package]]
-name = "dusk-consensus"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ba93b03b0dc35598763c039973c77c12f51475fc31ac20a9add5faa03e0bdde"
-dependencies = [
- "anyhow",
- "async-trait",
- "dusk-bytes",
- "dusk-core 1.1.0",
- "dusk-merkle",
- "dusk-node-data 1.1.0",
- "hex",
- "num-bigint",
- "sha3",
- "thiserror",
- "tokio",
- "tracing",
-]
-
 [[package]]
 name = "dusk-consensus"
 version = "1.0.2-alpha.1"
@@ -1646,9 +1626,9 @@ dependencies = [
  "async-trait",
  "criterion",
  "dusk-bytes",
- "dusk-core 1.1.0",
+ "dusk-core",
  "dusk-merkle",
- "dusk-node-data 1.1.0",
+ "dusk-node-data",
  "hex",
  "num-bigint",
  "rand 0.8.5",
@@ -1658,33 +1638,6 @@ dependencies = [
  "tracing",
 ]
 
-[[package]]
-name = "dusk-core"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f59efed0e9cae4161db7ab01609e59177c6b416282e37c75287ea2a165a31be"
-dependencies = [
- "ark-bn254",
- "ark-groth16",
- "ark-relations",
- "ark-serialize",
- "bls12_381-bls 0.5.0",
- "bytecheck",
- "dusk-bls12_381 0.14.1",
- "dusk-bytes",
- "dusk-jubjub",
- "dusk-plonk",
- "dusk-poseidon",
- "ff",
- "jubjub-schnorr",
- "phoenix-circuits",
- "phoenix-core",
- "piecrust-uplink",
- "poseidon-merkle",
- "rand 0.8.5",
- "rkyv",
-]
-
 [[package]]
 name = "dusk-core"
 version = "1.1.1-alpha.1"
@@ -1746,38 +1699,6 @@ dependencies = [
  "rkyv",
 ]
 
-[[package]]
-name = "dusk-node"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0441c97b1730ba96bd6eda42a8bfdfb40d4e6727a45a65924752a16f6ae69fad"
-dependencies = [
- "anyhow",
- "async-channel",
- "async-trait",
- "dusk-bytes",
- "dusk-consensus 1.0.1",
- "dusk-core 1.1.0",
- "dusk-node-data 1.1.0",
- "hex",
- "humantime-serde",
- "kadcast",
- "memory-stats",
- "metrics",
- "metrics-exporter-prometheus",
- "rkyv",
- "rocksdb",
- "serde",
- "serde_json",
- "serde_with",
- "smallvec",
- "sqlx",
- "thiserror",
- "time-util",
- "tokio",
- "tracing",
-]
-
 [[package]]
 name = "dusk-node"
 version = "1.1.1-alpha.1"
@@ -1787,9 +1708,9 @@ dependencies = [
  "async-trait",
  "criterion",
  "dusk-bytes",
- "dusk-consensus 1.0.1",
- "dusk-core 1.1.0",
- "dusk-node-data 1.1.0",
+ "dusk-consensus",
+ "dusk-core",
+ "dusk-node-data",
  "fake",
  "hex",
  "humantime-serde",
@@ -1812,33 +1733,6 @@ dependencies = [
  "tracing",
 ]
 
-[[package]]
-name = "dusk-node-data"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c9898926e038094f5b0a23af0f61ea0271fedbb86d9cbb3b9c5d9eb47f02f41d"
-dependencies = [
- "aes 0.7.5",
- "anyhow",
- "async-channel",
- "base64 0.22.1",
- "block-modes",
- "bs58",
- "chrono",
- "dusk-bytes",
- "dusk-core 1.1.0",
- "fake",
- "hex",
- "rand 0.8.5",
- "serde",
- "serde_json",
- "serde_with",
- "sha2 0.10.8",
- "sha3",
- "thiserror",
- "tracing",
-]
-
 [[package]]
 name = "dusk-node-data"
 version = "1.1.1-alpha.1"
@@ -1851,7 +1745,7 @@ dependencies = [
  "bs58",
  "chrono",
  "dusk-bytes",
- "dusk-core 1.1.0",
+ "dusk-core",
  "fake",
  "hex",
  "rand 0.8.5",
@@ -1914,12 +1808,12 @@ dependencies = [
  "criterion",
  "dirs",
  "dusk-bytes",
- "dusk-consensus 1.0.1",
- "dusk-core 1.1.0",
- "dusk-node 1.1.0",
- "dusk-node-data 1.1.0",
- "dusk-vm 1.1.0",
- "dusk-wallet-core 1.1.0",
+ "dusk-consensus",
+ "dusk-core",
+ "dusk-node",
+ "dusk-node-data",
+ "dusk-vm",
+ "dusk-wallet-core",
  "ff",
  "futures",
  "futures-util",
@@ -1935,9 +1829,9 @@ dependencies = [
  "rand 0.8.5",
  "reqwest",
  "rkyv",
- "rusk-profile 1.0.1",
- "rusk-prover 1.1.0",
- "rusk-recovery 1.0.3",
+ "rusk-profile",
+ "rusk-prover",
+ "rusk-recovery",
  "rustc_tools_util",
  "rustls-pemfile",
  "semver",
@@ -1965,22 +1859,6 @@ dependencies = [
  "zeroize",
 ]
 
-[[package]]
-name = "dusk-vm"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fd93de74b9906727d9d58af528e34650a37b9d7edee6116b4bf24682370cffe"
-dependencies = [
- "blake2b_simd",
- "blake3",
- "dusk-bytes",
- "dusk-core 1.1.0",
- "dusk-poseidon",
- "lru",
- "piecrust",
- "rkyv",
-]
-
 [[package]]
 name = "dusk-vm"
 version = "1.1.1-alpha.1"
@@ -1988,7 +1866,7 @@ dependencies = [
  "blake2b_simd",
  "blake3",
  "dusk-bytes",
- "dusk-core 1.1.0",
+ "dusk-core",
  "dusk-poseidon",
  "ff",
  "lru",
@@ -1998,25 +1876,6 @@ dependencies = [
  "rkyv",
 ]
 
-[[package]]
-name = "dusk-wallet-core"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4533c6298486bf3378dc0cd231613811a8973a037f6d94975f32d6e3a0f07f4f"
-dependencies = [
- "blake3",
- "bytecheck",
- "dlmalloc",
- "dusk-bytes",
- "dusk-core 1.1.0",
- "ff",
- "rand 0.8.5",
- "rand_chacha 0.3.1",
- "rkyv",
- "sha2 0.10.8",
- "zeroize",
-]
-
 [[package]]
 name = "dusk-wallet-core"
 version = "1.1.1-alpha.1"
@@ -2025,7 +1884,7 @@ dependencies = [
  "bytecheck",
  "dlmalloc",
  "dusk-bytes",
- "dusk-core 1.1.0",
+ "dusk-core",
  "ff",
  "rand 0.8.5",
  "rand_chacha 0.3.1",
@@ -2708,7 +2567,7 @@ name = "host_fn"
 version = "0.2.0"
 dependencies = [
  "dusk-bytes",
- "dusk-core 1.1.0",
+ "dusk-core",
 ]
 
 [[package]]
@@ -4457,23 +4316,6 @@ dependencies = [
  "zeroize",
 ]
 
-[[package]]
-name = "rusk-profile"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "096be7f24357ebde8859b56c423b694278d4d151ab055b14d445dfd749efed69"
-dependencies = [
- "blake3",
- "console",
- "dirs",
- "hex",
- "serde",
- "sha2 0.10.8",
- "toml",
- "tracing",
- "version_check",
-]
-
 [[package]]
 name = "rusk-profile"
 version = "1.0.2-alpha.1"
@@ -4489,65 +4331,20 @@ dependencies = [
  "version_check",
 ]
 
-[[package]]
-name = "rusk-prover"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "469cbbdd11c2fde62fabe5ca710eb274d36aa01941a12625ac1b6c97320568db"
-dependencies = [
- "dusk-bytes",
- "dusk-core 1.1.0",
- "dusk-plonk",
- "hex",
- "once_cell",
- "rand 0.8.5",
- "rusk-profile 1.0.1",
- "tracing",
-]
-
 [[package]]
 name = "rusk-prover"
 version = "1.1.1-alpha.1"
 dependencies = [
  "dusk-bytes",
- "dusk-core 1.1.0",
+ "dusk-core",
  "dusk-plonk",
  "hex",
  "once_cell",
  "rand 0.8.5",
- "rusk-profile 1.0.1",
+ "rusk-profile",
  "tracing",
 ]
 
-[[package]]
-name = "rusk-recovery"
-version = "1.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e42cccdbd038aa1d17c4eb053a4817813adf2c6d68ea392bcc20efee1de78bc"
-dependencies = [
- "bs58",
- "cargo_toml",
- "dusk-bytes",
- "dusk-core 1.1.0",
- "dusk-plonk",
- "dusk-vm 1.1.0",
- "ff",
- "flate2",
- "hex",
- "http_req",
- "rand 0.8.5",
- "reqwest",
- "rusk-profile 1.0.1",
- "serde",
- "serde_derive",
- "tar",
- "tokio",
- "toml",
- "tracing",
- "url",
- "zip",
-]
-
 [[package]]
 name = "rusk-recovery"
 version = "1.0.4-alpha.1"
@@ -4555,16 +4352,16 @@ dependencies = [
  "bs58",
  "cargo_toml",
  "dusk-bytes",
- "dusk-core 1.1.0",
+ "dusk-core",
  "dusk-plonk",
- "dusk-vm 1.1.0",
+ "dusk-vm",
  "ff",
  "flate2",
  "hex",
  "http_req",
  "rand 0.8.5",
  "reqwest",
- "rusk-profile 1.0.1",
+ "rusk-profile",
  "serde",
  "serde_derive",
  "tar",
@@ -4591,8 +4388,8 @@ dependencies = [
  "crossterm",
  "dirs",
  "dusk-bytes",
- "dusk-core 1.1.0",
- "dusk-wallet-core 1.1.0",
+ "dusk-core",
+ "dusk-wallet-core",
  "flume 0.10.14",
  "futures",
  "hex",
@@ -5246,13 +5043,13 @@ version = "0.8.0"
 dependencies = [
  "criterion",
  "dusk-bytes",
- "dusk-core 1.1.0",
- "dusk-vm 1.1.0",
- "dusk-wallet-core 1.1.0",
+ "dusk-core",
+ "dusk-vm",
+ "dusk-wallet-core",
  "ff",
  "rand 0.8.5",
  "rkyv",
- "rusk-prover 1.1.0",
+ "rusk-prover",
 ]
 
 [[package]]
@@ -5731,14 +5528,14 @@ name = "transfer-contract"
 version = "0.10.1"
 dependencies = [
  "dusk-bytes",
- "dusk-core 1.1.0",
- "dusk-vm 1.1.0",
+ "dusk-core",
+ "dusk-vm",
  "ff",
  "rand 0.8.5",
  "ringbuffer",
  "rkyv",
- "rusk-profile 1.0.1",
- "rusk-prover 1.1.0",
+ "rusk-profile",
+ "rusk-prover",
 ]
 
 [[package]]
diff --git a/Cargo.toml b/Cargo.toml
index efde38294f..cd05c4c518 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -30,24 +30,24 @@ resolver = "2"
 
 [workspace.dependencies]
 # Workspace internal dependencies
-dusk-consensus = "1.0.1"
-# dusk-consensus = { version = "1.0.2-alpha.1", path = "./consensus/" }
-dusk-core = "1.1.0"
-# dusk-core = { version = "1.1.0", path = "./core/" }
-dusk-vm = "1.1.0"
-# dusk-vm = { version = "1.1.0", path = "./vm/" }
-node = { version = "1.1.0", package = "dusk-node" }
-# node = { version = "1.1.0", path = "./node/", package = "dusk-node" }
-node-data = { version = "1.1.0", package = "dusk-node-data" }
-# node-data = { version = "1.1.0", path = "./node-data/", package = "dusk-node-data" }
-rusk-profile = "1.0.1"
-# rusk-profile = { version = "1.0.2-alpha.1", path = "./rusk-profile/" }
-rusk-prover = "1.1.0"
-# rusk-prover = { version = "1.1.1-alpha.1", path = "./rusk-prover/" }
-rusk-recovery = "1.0.3"
-# rusk-recovery = { version = "1.0.4-alpha.1", path = "./rusk-recovery/" }
-wallet-core = { version = "1.1.0", package = "dusk-wallet-core" }
-# wallet-core = { version = "1.1.1-alpha.1", path = "./wallet-core/", package = "dusk-wallet-core" }
+# dusk-consensus = "1.0.1"
+dusk-consensus = { version = "1.0.2-alpha.1", path = "./consensus/" }
+# dusk-core = "1.1.0"
+dusk-core = { version = "1.1.1-alpha.1", path = "./core/" }
+# dusk-vm = "1.1.0"
+dusk-vm = { version = "1.1.1-alpha.1", path = "./vm/" }
+# node = { version = "1.1.0", package = "dusk-node" }
+node = { version = "1.1.1-alpha.1", path = "./node/", package = "dusk-node" }
+# node-data = { version = "1.1.0", package = "dusk-node-data" }
+node-data = { version = "1.1.1-alpha.1", path = "./node-data/", package = "dusk-node-data" }
+# rusk-profile = "1.0.1"
+rusk-profile = { version = "1.0.2-alpha.1", path = "./rusk-profile/" }
+# rusk-prover = "1.1.0"
+rusk-prover = { version = "1.1.1-alpha.1", path = "./rusk-prover/" }
+# rusk-recovery = "1.0.3"
+rusk-recovery = { version = "1.0.4-alpha.1", path = "./rusk-recovery/" }
+# wallet-core = { version = "1.1.0", package = "dusk-wallet-core" }
+wallet-core = { version = "1.1.1-alpha.1", path = "./wallet-core/", package = "dusk-wallet-core" }
 
 # Dusk dependencies outside the workspace
 bls12_381-bls = { version = "0.5", default-features = false }
diff --git a/node-data/CHANGELOG.md b/node-data/CHANGELOG.md
index 3266884a6f..16b5f7b57a 100644
--- a/node-data/CHANGELOG.md
+++ b/node-data/CHANGELOG.md
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ## [Unreleased]
 
+### Removed
+
+- Remove `WrappedContractId` [#3503]
+
 ## [1.1.0] - 2025-02-14
 
 ### Added
@@ -31,6 +35,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - Add Types used for interacting with Dusk node 
 
 <!-- Issues -->
+[#3503]: https://github.com/dusk-network/rusk/issues/3503]
 [#3464]: https://github.com/dusk-network/rusk/issues/3464
 [#3359]: https://github.com/dusk-network/rusk/issues/3359
 [#3405]: https://github.com/dusk-network/rusk/issues/3405
diff --git a/node-data/Cargo.toml b/node-data/Cargo.toml
index e922251ae0..e46849f2a6 100644
--- a/node-data/Cargo.toml
+++ b/node-data/Cargo.toml
@@ -13,7 +13,7 @@ sha3 = { workspace = true }
 sha2 = { workspace = true }
 rand = { workspace = true, features = ["std_rng"] }
 hex = { workspace = true }
-dusk-core = { workspace = true }
+dusk-core = { workspace = true, features = ["serde"] }
 
 block-modes = { workspace = true }
 aes = { workspace = true }
diff --git a/node-data/src/events/contract.rs b/node-data/src/events/contract.rs
index 15ca77a6d4..24ad68bda9 100644
--- a/node-data/src/events/contract.rs
+++ b/node-data/src/events/contract.rs
@@ -6,9 +6,8 @@
 
 //! This module defines the contract event type and related types.
 
-use anyhow::Result;
-use dusk_core::abi::{ContractId, Event, CONTRACT_ID_BYTES};
-use serde::{Deserialize, Deserializer, Serialize, Serializer};
+use dusk_core::abi::{ContractId, Event};
+use serde::{Deserialize, Serialize};
 
 pub const ORIGIN_HASH_BYTES: usize = 32;
 /// Origin hash of a contract event. This is in most cases the transaction hash.
@@ -24,71 +23,12 @@ pub struct ContractTxEvent {
     pub origin: OriginHash,
 }
 
-#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
-#[repr(C)]
-pub struct WrappedContractId(pub ContractId);
-
-impl TryFrom<String> for WrappedContractId {
-    type Error = anyhow::Error;
-
-    fn try_from(value: String) -> std::result::Result<Self, Self::Error> {
-        let source_bytes = hex::decode(value)?;
-        let mut source_array = [0u8; CONTRACT_ID_BYTES];
-
-        if source_bytes.len() != CONTRACT_ID_BYTES {
-            return Err(anyhow::anyhow!(
-                "Invalid length: expected {} bytes, got {}",
-                CONTRACT_ID_BYTES,
-                source_bytes.len()
-            ));
-        } else {
-            source_array.copy_from_slice(&source_bytes);
-        }
-
-        Ok(WrappedContractId(ContractId::from_bytes(source_array)))
-    }
-}
-
-impl Serialize for WrappedContractId {
-    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
-    where
-        S: Serializer,
-    {
-        let source_hex = hex::encode(self.0.as_bytes());
-        s.serialize_str(&source_hex)
-    }
-}
-
-impl<'de> Deserialize<'de> for WrappedContractId {
-    fn deserialize<D>(deserializer: D) -> Result<WrappedContractId, D::Error>
-    where
-        D: Deserializer<'de>,
-    {
-        let source_hex: String = Deserialize::deserialize(deserializer)?;
-        let source_bytes =
-            hex::decode(source_hex).map_err(serde::de::Error::custom)?;
-        let mut source_array = [0u8; CONTRACT_ID_BYTES];
-
-        if source_bytes.len() != CONTRACT_ID_BYTES {
-            return Err(serde::de::Error::custom(format!(
-                "Invalid length: expected {} bytes, got {}",
-                CONTRACT_ID_BYTES,
-                source_bytes.len()
-            )));
-        } else {
-            source_array.copy_from_slice(&source_bytes);
-        }
-
-        Ok(WrappedContractId(ContractId::from_bytes(source_array)))
-    }
-}
-
 /// Wrapper around a contract event that is to be archived or sent to a
 /// websocket client.
 #[serde_with::serde_as]
 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
 pub struct ContractEvent {
-    pub target: WrappedContractId,
+    pub target: ContractId,
     pub topic: String,
     #[serde_as(as = "serde_with::hex::Hex")]
     pub data: Vec<u8>,
@@ -97,7 +37,7 @@ pub struct ContractEvent {
 impl From<Event> for ContractEvent {
     fn from(event: Event) -> Self {
         Self {
-            target: WrappedContractId(event.source),
+            target: event.source,
             topic: event.topic,
             data: event.data,
         }
@@ -107,7 +47,7 @@ impl From<Event> for ContractEvent {
 impl From<ContractEvent> for Event {
     fn from(contract_event: ContractEvent) -> Self {
         Event {
-            source: contract_event.target.0,
+            source: contract_event.target,
             topic: contract_event.topic,
             data: contract_event.data,
         }
@@ -116,6 +56,8 @@ impl From<ContractEvent> for Event {
 
 #[cfg(test)]
 mod tests {
+    use dusk_core::abi::CONTRACT_ID_BYTES;
+
     use super::*;
 
     fn exec_core_event() -> Event {
diff --git a/node/src/archive/moonlight.rs b/node/src/archive/moonlight.rs
index f66bf2e5bf..865790aaad 100644
--- a/node/src/archive/moonlight.rs
+++ b/node/src/archive/moonlight.rs
@@ -762,7 +762,7 @@ mod tests {
         ConvertEvent, DepositEvent, MoonlightTransactionEvent, WithdrawEvent,
     };
     use node_data::events::contract::{
-        ContractEvent, ContractTxEvent, WrappedContractId, ORIGIN_HASH_BYTES,
+        ContractEvent, ContractTxEvent, ORIGIN_HASH_BYTES,
     };
     use rand::distributions::Alphanumeric;
     use rand::rngs::StdRng;
@@ -789,9 +789,7 @@ mod tests {
     fn dummy_data(topic: &str) -> ContractTxEvent {
         ContractTxEvent {
             event: ContractEvent {
-                target: WrappedContractId(ContractId::from_bytes(
-                    [0; CONTRACT_ID_BYTES],
-                )),
+                target: ContractId::from_bytes([0; CONTRACT_ID_BYTES]),
                 topic: topic.to_owned(),
                 data: vec![1, 6, 1, 8],
             },
@@ -804,9 +802,8 @@ mod tests {
 
         ContractTxEvent {
             event: ContractEvent {
-                target: WrappedContractId(
-                    dusk_core::transfer::TRANSFER_CONTRACT,
-                ),
+                target: dusk_core::transfer::TRANSFER_CONTRACT,
+
                 topic: "phoenix".to_string(),
                 data: rkyv::to_bytes::<_, 256>(&fake_phoenix_tx_event_data)
                     .unwrap()
@@ -825,9 +822,8 @@ mod tests {
 
         ContractTxEvent {
             event: ContractEvent {
-                target: WrappedContractId(
-                    dusk_core::transfer::TRANSFER_CONTRACT,
-                ),
+                target: dusk_core::transfer::TRANSFER_CONTRACT,
+
                 topic: "convert".to_string(),
                 data: rkyv::to_bytes::<_, 256>(&convert_event)
                     .unwrap()
@@ -855,9 +851,8 @@ mod tests {
 
         ContractTxEvent {
             event: ContractEvent {
-                target: WrappedContractId(
-                    dusk_core::transfer::TRANSFER_CONTRACT,
-                ),
+                target: dusk_core::transfer::TRANSFER_CONTRACT,
+
                 topic: "moonlight".to_string(),
                 data: rkyv::to_bytes::<_, 256>(&moonlight_tx_event)
                     .unwrap()
@@ -876,9 +871,7 @@ mod tests {
 
         ContractTxEvent {
             event: ContractEvent {
-                target: WrappedContractId(
-                    dusk_core::transfer::TRANSFER_CONTRACT,
-                ),
+                target: dusk_core::transfer::TRANSFER_CONTRACT,
                 topic: "withdraw".to_string(),
                 data: rkyv::to_bytes::<_, 256>(&withdraw_event)
                     .unwrap()
@@ -897,9 +890,8 @@ mod tests {
 
         ContractTxEvent {
             event: ContractEvent {
-                target: WrappedContractId(
-                    dusk_core::transfer::TRANSFER_CONTRACT,
-                ),
+                target: dusk_core::transfer::TRANSFER_CONTRACT,
+
                 topic: "deposit".to_string(),
                 data: rkyv::to_bytes::<_, 256>(&deposit_event)
                     .unwrap()
@@ -918,9 +910,7 @@ mod tests {
 
         ContractTxEvent {
             event: ContractEvent {
-                target: WrappedContractId(
-                    dusk_core::transfer::TRANSFER_CONTRACT,
-                ),
+                target: dusk_core::transfer::TRANSFER_CONTRACT,
                 topic: "deposit".to_string(),
                 data: rkyv::to_bytes::<_, 256>(&deposit_event)
                     .unwrap()
@@ -1186,10 +1176,7 @@ mod tests {
         assert_eq!(fetched_tx1[0].origin(), &[4; 32]);
         fetched_tx1[0].events().iter().for_each(|e| {
             assert_eq!(e.topic, "moonlight");
-            assert_eq!(
-                e.target,
-                WrappedContractId(dusk_core::transfer::TRANSFER_CONTRACT)
-            );
+            assert_eq!(e.target, usk_core::transfer::TRANSFER_CONTRACT);
 
             let moonlight_event =
                 rkyv::from_bytes::<MoonlightTransactionEvent>(&e.data).unwrap();
@@ -1208,10 +1195,7 @@ mod tests {
             assert_eq!(fetched_tx.origin(), &[i as u8; ORIGIN_HASH_BYTES]);
             fetched_tx.events().iter().for_each(|e| {
                 assert_eq!(e.topic, "moonlight");
-                assert_eq!(
-                    e.target,
-                    WrappedContractId(dusk_core::transfer::TRANSFER_CONTRACT)
-                );
+                assert_eq!(e.target, dusk_core::transfer::TRANSFER_CONTRACT);
 
                 let moonlight_event =
                     rkyv::from_bytes::<MoonlightTransactionEvent>(&e.data)
diff --git a/node/src/archive/sqlite.rs b/node/src/archive/sqlite.rs
index feb9d88f57..335f49d6ba 100644
--- a/node/src/archive/sqlite.rs
+++ b/node/src/archive/sqlite.rs
@@ -247,7 +247,7 @@ impl Archive {
             let event = data::ArchivedEvent {
                 origin: hex::encode(event.origin),
                 topic: event.event.topic,
-                source: event.event.target.0.to_string(),
+                source: event.event.target.to_string(),
                 data: event.event.data,
             };
 
@@ -305,7 +305,7 @@ impl Archive {
         1. Any PhoenixTransactionEvent (through notes & refund_note)
         */
         let phoenix_event_present = events.iter().any(|event| {
-            event.event.target.0 == dusk_core::transfer::TRANSFER_CONTRACT
+            event.event.target == dusk_core::transfer::TRANSFER_CONTRACT
                 && event.event.topic == dusk_core::transfer::PHOENIX_TOPIC
         });
 
@@ -343,7 +343,7 @@ impl Archive {
             let origin = hex::encode(ident.origin());
 
             for event in events {
-                let source = event.target.0.to_string();
+                let source = event.target.to_string();
 
                 sqlx::query!(
                     r#"INSERT INTO finalized_events (block_height, block_hash, origin, topic, source, data) VALUES (?, ?, ?, ?, ?, ?)"#,
@@ -421,12 +421,38 @@ impl Archive {
 }
 
 mod data {
+    use dusk_core::abi::{ContractId, CONTRACT_ID_BYTES};
     use node_data::events::contract::{
         ContractEvent, ContractTxEvent, ORIGIN_HASH_BYTES,
     };
     use serde::{Deserialize, Serialize};
     use sqlx::FromRow;
 
+    // TODO: implement TryFrom<String> in piecrust for ContractId
+    // Remove this once https://github.com/dusk-network/piecrust/pull/421 is available
+    struct WrappedContractId(pub ContractId);
+
+    impl TryFrom<String> for WrappedContractId {
+        type Error = anyhow::Error;
+
+        fn try_from(value: String) -> std::result::Result<Self, Self::Error> {
+            let source_bytes = hex::decode(value)?;
+            let mut source_array = [0u8; CONTRACT_ID_BYTES];
+
+            if source_bytes.len() != CONTRACT_ID_BYTES {
+                return Err(anyhow::anyhow!(
+                    "Invalid length: expected {} bytes, got {}",
+                    CONTRACT_ID_BYTES,
+                    source_bytes.len()
+                ));
+            } else {
+                source_array.copy_from_slice(&source_bytes);
+            }
+
+            Ok(WrappedContractId(ContractId::from_bytes(source_array)))
+        }
+    }
+
     /// Archived ContractTxEvent
     ///
     /// This struct is used to store the archived events in the SQLite database.
@@ -465,9 +491,11 @@ mod data {
                 origin_array.copy_from_slice(&origin);
             }
 
+            let target = WrappedContractId::try_from(value.source)?;
+
             Ok(ContractTxEvent {
                 event: ContractEvent {
-                    target: value.source.try_into()?,
+                    target: target.0,
                     topic: value.topic,
                     data: value.data,
                 },
@@ -502,7 +530,7 @@ mod tests {
     use std::path::PathBuf;
 
     use dusk_core::abi::ContractId;
-    use node_data::events::contract::{ContractEvent, WrappedContractId};
+    use node_data::events::contract::ContractEvent;
     use rand::distributions::Alphanumeric;
     use rand::Rng;
     use util::truncate_string;
@@ -546,7 +574,7 @@ mod tests {
         vec![
             ContractTxEvent {
                 event: ContractEvent {
-                    target: WrappedContractId(ContractId::from_bytes([0; 32])),
+                    target: ContractId::from_bytes([0; 32]),
                     topic: "contract1".to_string(),
                     data: vec![1, 6, 1, 8],
                 },
@@ -554,7 +582,7 @@ mod tests {
             },
             ContractTxEvent {
                 event: ContractEvent {
-                    target: WrappedContractId(ContractId::from_bytes([1; 32])),
+                    target: ContractId::from_bytes([1; 32]),
                     topic: "contract2".to_string(),
                     data: vec![1, 2, 3],
                 },
@@ -583,7 +611,7 @@ mod tests {
             events.iter().zip(fetched_events.iter())
         {
             assert_eq!(
-                contract_tx_event.event.target.0.to_string(),
+                contract_tx_event.event.target.to_string(),
                 fetched_event.source /* if this fails do hex::decode here
                                       * and to bytes above */
             );
diff --git a/node/src/archive/transformer.rs b/node/src/archive/transformer.rs
index 5d35fc541e..ffddde4905 100644
--- a/node/src/archive/transformer.rs
+++ b/node/src/archive/transformer.rs
@@ -201,7 +201,7 @@ fn record_flows(
         .filter(|event| {
             // Make sure that the events originate from the transfer
             // contract.
-            if event.target.0 != TRANSFER_CONTRACT {
+            if event.target != TRANSFER_CONTRACT {
                 return false;
             }
 
diff --git a/node/src/chain/acceptor.rs b/node/src/chain/acceptor.rs
index 8523018091..a0db0f86ef 100644
--- a/node/src/chain/acceptor.rs
+++ b/node/src/chain/acceptor.rs
@@ -793,7 +793,7 @@ impl<DB: database::DB, VM: vm::VMExecution, N: Network> Acceptor<N, DB, VM> {
 
             let mut stakes = vec![];
             for event in contract_events {
-                if event.event.target.0 == STAKE_CONTRACT {
+                if event.event.target == STAKE_CONTRACT {
                     stakes.push(event.event);
                 }
             }
diff --git a/rusk/src/lib/http.rs b/rusk/src/lib/http.rs
index 420af4da34..77546237ae 100644
--- a/rusk/src/lib/http.rs
+++ b/rusk/src/lib/http.rs
@@ -674,9 +674,7 @@ mod tests {
     use super::*;
 
     use dusk_core::abi::ContractId;
-    use node_data::events::contract::{
-        ContractEvent, ContractTxEvent, WrappedContractId,
-    };
+    use node_data::events::contract::{ContractEvent, ContractTxEvent};
     use std::net::TcpStream;
     use tungstenite::client;
 
@@ -848,17 +846,15 @@ mod tests {
         )
         .expect("Session ID should be parsed");
 
-        const SUB_CONTRACT_ID: WrappedContractId =
-            WrappedContractId(ContractId::from_bytes([1; 32]));
-        const MAYBE_SUB_CONTRACT_ID: WrappedContractId =
-            WrappedContractId(ContractId::from_bytes([2; 32]));
-        const NON_SUB_CONTRACT_ID: WrappedContractId =
-            WrappedContractId(ContractId::from_bytes([3; 32]));
+        const SUB_CONTRACT_ID: ContractId = ContractId::from_bytes([1; 32]);
+        const MAYBE_SUB_CONTRACT_ID: ContractId =
+            ContractId::from_bytes([2; 32]);
+        const NON_SUB_CONTRACT_ID: ContractId = ContractId::from_bytes([3; 32]);
 
         const TOPIC: &str = "topic";
 
-        let sub_contract_id_hex = hex::encode(SUB_CONTRACT_ID.0);
-        let maybe_sub_contract_id_hex = hex::encode(MAYBE_SUB_CONTRACT_ID.0);
+        let sub_contract_id_hex = hex::encode(SUB_CONTRACT_ID);
+        let maybe_sub_contract_id_hex = hex::encode(MAYBE_SUB_CONTRACT_ID);
 
         let client = reqwest::Client::new();
 
diff --git a/rusk/src/lib/http/chain/graphql/archive/data.rs b/rusk/src/lib/http/chain/graphql/archive/data.rs
index 3eeb6143de..d268f85718 100644
--- a/rusk/src/lib/http/chain/graphql/archive/data.rs
+++ b/rusk/src/lib/http/chain/graphql/archive/data.rs
@@ -49,6 +49,8 @@ impl ContractEvents {
 /// TODO: #2773 add serde feature to dusk-core
 pub mod deserialized_archive_data {
     use super::*;
+
+    use dusk_core::abi::ContractId;
     use dusk_core::stake::STAKE_CONTRACT;
     use dusk_core::transfer::withdraw::WithdrawReceiver;
     use dusk_core::transfer::{
@@ -56,9 +58,7 @@ pub mod deserialized_archive_data {
         CONVERT_TOPIC, DEPOSIT_TOPIC, MINT_TOPIC, MOONLIGHT_TOPIC,
         TRANSFER_CONTRACT, WITHDRAW_TOPIC,
     };
-    use node_data::events::contract::{
-        ContractEvent, OriginHash, WrappedContractId,
-    };
+    use node_data::events::contract::{ContractEvent, OriginHash};
     use serde::ser::SerializeStruct;
     use serde::{Deserialize, Serialize};
 
@@ -128,10 +128,7 @@ pub mod deserialized_archive_data {
         {
             let withdraw_event = &self.0;
             let mut state = serializer.serialize_struct("WithdrawEvent", 3)?;
-            state.serialize_field(
-                "sender",
-                &WrappedContractId(withdraw_event.sender),
-            )?;
+            state.serialize_field("sender", &withdraw_event.sender)?;
             state.serialize_field(
                 "receiver",
                 &match withdraw_event.receiver {
@@ -197,10 +194,7 @@ pub mod deserialized_archive_data {
                     .sender
                     .map(|pk| bs58::encode(pk.to_bytes()).into_string()),
             )?;
-            state.serialize_field(
-                "receiver",
-                &WrappedContractId(deposit_event.receiver),
-            )?;
+            state.serialize_field("receiver", &deposit_event.receiver)?;
             state.serialize_field("value", &deposit_event.value)?;
 
             state.end()
@@ -209,14 +203,14 @@ pub mod deserialized_archive_data {
 
     #[derive(Debug, Clone, PartialEq, Serialize)]
     pub struct DeserializedContractEvent {
-        pub target: WrappedContractId,
+        pub target: ContractId,
         pub topic: String,
         pub data: serde_json::Value,
     }
 
     impl From<ContractEvent> for DeserializedContractEvent {
         fn from(event: ContractEvent) -> Self {
-            let deserialized_data = if event.target.0 == TRANSFER_CONTRACT {
+            let deserialized_data = if event.target == TRANSFER_CONTRACT {
                 match event.topic.as_str() {
                     MOONLIGHT_TOPIC => rkyv::from_bytes::<
                         MoonlightTransactionEvent,
diff --git a/rusk/src/lib/http/chain/graphql/archive/events.rs b/rusk/src/lib/http/chain/graphql/archive/events.rs
index ea9369a4b8..29e56e0144 100644
--- a/rusk/src/lib/http/chain/graphql/archive/events.rs
+++ b/rusk/src/lib/http/chain/graphql/archive/events.rs
@@ -6,12 +6,10 @@
 
 //! Module for GraphQL that relates to stored events in the archive.
 
-use async_graphql::{Context, FieldError, FieldResult, Object};
-use dusk_core::abi::CONTRACT_ID_BYTES;
-use node_data::events::contract::WrappedContractId;
-
 use super::data::ContractEvents;
 use crate::http::chain::graphql::{DBContext, OptResult};
+use async_graphql::{Context, FieldError, FieldResult, Object};
+use dusk_core::abi::{ContractId, CONTRACT_ID_BYTES};
 
 pub async fn events_by_height(
     ctx: &Context<'_>,
diff --git a/rusk/src/lib/http/event.rs b/rusk/src/lib/http/event.rs
index 21184a062a..30178611cd 100644
--- a/rusk/src/lib/http/event.rs
+++ b/rusk/src/lib/http/event.rs
@@ -736,7 +736,7 @@ impl From<node_data::events::contract::ContractTxEvent> for RuesEvent {
         Self {
             uri: RuesEventUri {
                 component: "contracts".into(),
-                entity: Some(hex::encode(event.target.0)),
+                entity: Some(hex::encode(event.target.to_bytes())),
                 topic: event.topic,
             },
             data: event.data.into(),


Test patch: